1
0
mirror of https://github.com/nlohmann/json synced 2024-11-22 20:10:06 +00:00

clean up after #193

This commit is contained in:
Niels 2016-01-26 19:50:49 +01:00
parent e46cc6327f
commit 707732a53e
4 changed files with 1012 additions and 545 deletions

View File

@ -390,7 +390,7 @@ I deeply appreciate the help of the following people.
- [406345](https://github.com/406345) fixed two small warnings.
- [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function.
- [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines.
- [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping.
- [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping. He further added support for unsigned integer numbers.
- [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file.
Thanks a lot for helping out!
@ -409,7 +409,7 @@ $ make
$ ./json_unit "*"
===============================================================================
All tests passed (3343329 assertions in 29 test cases)
All tests passed (3344278 assertions in 29 test cases)
```
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).

File diff suppressed because it is too large Load Diff

View File

@ -124,8 +124,8 @@ default; will be used in @ref string_t)
in @ref boolean_t)
@tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by
default; will be used in @ref number_integer_t)
@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c `uint64_t` by
default; will be used in @ref number_unsigned_t)
@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
`uint64_t` by default; will be used in @ref number_unsigned_t)
@tparam NumberFloatType type for JSON floating-point numbers (@c `double` by
default; will be used in @ref number_float_t)
@tparam AllocatorType type of the allocator to use (@c `std::allocator` by
@ -485,9 +485,9 @@ class basic_json
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is a
C++ allows more precise storage if it is known whether the number is a
signed integer, an unsigned integer or a floating-point number. Therefore,
three different types, @ref number_integer_t, @ref number_unsigned_t and
three different types, @ref number_integer_t, @ref number_unsigned_t and
@ref number_float_t are used.
To store integer numbers in C++, a type is defined by the template
@ -556,9 +556,9 @@ class basic_json
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is a
C++ allows more precise storage if it is known whether the number is a
signed integer, an unsigned integer or a floating-point number. Therefore,
three different types, @ref number_integer_t, @ref number_unsigned_t and
three different types, @ref number_integer_t, @ref number_unsigned_t and
@ref number_float_t are used.
To store unsigned integer numbers in C++, a type is defined by the template
@ -588,11 +588,11 @@ class basic_json
> An implementation may set limits on the range and precision of numbers.
When the default type is used, the maximal integer number that can be
stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number
that can be stored is `0`. Integer numbers
that are out of range will yield over/underflow when used in a constructor.
During deserialization, too large or small integer numbers will be
automatically be stored as @ref number_integer_t or @ref number_float_t.
stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
number that can be stored is `0`. Integer numbers that are out of range
will yield over/underflow when used in a constructor. During
deserialization, too large or small integer numbers will be automatically
be stored as @ref number_integer_t or @ref number_float_t.
[RFC 7159](http://rfc7159.net/rfc7159) further states:
> Note that when such software is used, numbers that are integers and are
@ -600,7 +600,7 @@ class basic_json
> that implementations will agree exactly on their numeric values.
As this range is a subrange (when considered in conjunction with the
number_integer_t type) of the exactly supported range [0, UINT64_MAX], this
number_integer_t type) of the exactly supported range [0, UINT64_MAX], this
class's integer type is interoperable.
#### Storage
@ -614,7 +614,7 @@ class basic_json
@since version 2.0.0
*/
using number_unsigned_t = NumberUnsignedType;
/*!
@brief a type for a number (floating-point)
@ -628,9 +628,9 @@ class basic_json
> permitted.
This description includes both integer and floating-point numbers. However,
C++ allows more precise storage if it is known whether the number is a
C++ allows more precise storage if it is known whether the number is a
signed integer, an unsigned integer or a floating-point number. Therefore,
three different types, @ref number_integer_t, @ref number_unsigned_t and
three different types, @ref number_integer_t, @ref number_unsigned_t and
@ref number_float_t are used.
To store floating-point numbers in C++, a type is defined by the template
@ -801,7 +801,7 @@ class basic_json
number_integer = number_integer_t(0);
break;
}
case value_t::number_unsigned:
{
number_unsigned = number_unsigned_t(0);
@ -1330,8 +1330,8 @@ class basic_json
template<typename CompatibleNumberIntegerType, typename
std::enable_if<
std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
CompatibleNumberIntegerType>::type
= 0>
basic_json(const CompatibleNumberIntegerType val) noexcept
@ -1344,7 +1344,7 @@ class basic_json
Create an unsigned integer number JSON value with a given content.
@tparam T helper type to compare number_unsigned_t and unsigned int
@tparam T helper type to compare number_unsigned_t and unsigned int
(not visible in) the interface.
@param[in] val an integer to create a JSON number from
@ -1365,14 +1365,14 @@ class basic_json
basic_json(const number_unsigned_t val)
: m_type(value_t::number_unsigned), m_value(val)
{}
/*!
@brief create an unsigned number (implicit)
Create an unsigned number JSON value with a given content. This constructor
allows any type that can be used to construct values of type @ref
number_unsigned_t. Examples may include the types `unsigned int`, `uint32_t`,
or `unsigned short`.
number_unsigned_t. Examples may include the types `unsigned int`,
`uint32_t`, or `unsigned short`.
@tparam CompatibleNumberUnsignedType an integer type which is compatible to
@ref number_unsigned_t.
@ -1386,13 +1386,13 @@ class basic_json
@since version 2.0.0
*/
template<typename CompatibleNumberUnsignedType, typename
std::enable_if<
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
!std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
CompatibleNumberUnsignedType>::type
= 0>
template < typename CompatibleNumberUnsignedType, typename
std::enable_if <
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
!std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
CompatibleNumberUnsignedType >::type
= 0 >
basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val))
@ -1781,7 +1781,7 @@ class basic_json
m_value.number_integer = first.m_object->m_value.number_integer;
break;
}
case value_t::number_unsigned:
{
assert(first.m_object != nullptr);
@ -1891,7 +1891,7 @@ class basic_json
m_value = other.m_value.number_integer;
break;
}
case value_t::number_unsigned:
{
m_value = other.m_value.number_unsigned;
@ -2183,9 +2183,10 @@ class basic_json
@liveexample{The following code exemplifies @ref is_number for all JSON
types.,is_number}
@sa @ref is_number_integer() -- check if value is an integer or unsigned
@sa @ref is_number_integer() -- check if value is an integer or unsigned
integer number
@sa @ref is_number_unsigned() -- check if value is an unsigned integer number
@sa @ref is_number_unsigned() -- check if value is an unsigned integer
number
@sa @ref is_number_float() -- check if value is a floating-point number
@since version 1.0.0
@ -2198,10 +2199,10 @@ class basic_json
/*!
@brief return whether value is an integer number
This function returns true iff the JSON value is an integer or unsigned
This function returns true iff the JSON value is an integer or unsigned
integer number. This excludes floating-point values.
@return `true` if type is an integer or unsigned integer number, `false`
@return `true` if type is an integer or unsigned integer number, `false`
otherwise.
@complexity Constant.
@ -2210,7 +2211,8 @@ class basic_json
JSON types.,is_number_integer}
@sa @ref is_number() -- check if value is a number
@sa @ref is_number_unsigned() -- check if value is an unsigned integer number
@sa @ref is_number_unsigned() -- check if value is an unsigned integer
number
@sa @ref is_number_float() -- check if value is a floating-point number
@since version 1.0.0
@ -2219,19 +2221,19 @@ class basic_json
{
return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
}
/*!
@brief return whether value is an unsigned integer number
This function returns true iff the JSON value is an unsigned integer number.
This excludes floating-point and (signed) integer values.
This function returns true iff the JSON value is an unsigned integer
number. This excludes floating-point and (signed) integer values.
@return `true` if type is an unsigned integer number, `false` otherwise.
@complexity Constant.
@sa @ref is_number() -- check if value is a number
@sa @ref is_number_integer() -- check if value is an integer or unsigned
@sa @ref is_number_integer() -- check if value is an integer or unsigned
integer number
@sa @ref is_number_float() -- check if value is a floating-point number
@ -2257,7 +2259,8 @@ class basic_json
@sa @ref is_number() -- check if value is number
@sa @ref is_number_integer() -- check if value is an integer number
@sa @ref is_number_unsigned() -- check if value is an unsigned integer number
@sa @ref is_number_unsigned() -- check if value is an unsigned integer
number
@since version 1.0.0
*/
@ -2525,7 +2528,7 @@ class basic_json
{
return static_cast<T>(m_value.number_integer);
}
case value_t::number_unsigned:
{
return static_cast<T>(m_value.number_unsigned);
@ -2615,7 +2618,7 @@ class basic_json
{
return is_number_integer() ? &m_value.number_integer : nullptr;
}
/// get a pointer to the value (unsigned number)
number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
{
@ -2627,7 +2630,7 @@ class basic_json
{
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
}
/// get a pointer to the value (floating-point number)
number_float_t* get_impl_ptr(number_float_t*) noexcept
{
@ -2725,7 +2728,7 @@ class basic_json
@warning The pointer becomes invalid if the underlying JSON object changes.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t.
@return pointer to the internally stored JSON value if the requested
@ -2776,7 +2779,7 @@ class basic_json
state.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t.
@return pointer to the internally stored JSON value if the requested
@ -2895,14 +2898,14 @@ class basic_json
@since version 1.0.0
*/
template<typename ValueType, typename
std::enable_if<
not std::is_pointer<ValueType>::value
and not std::is_same<ValueType, typename string_t::value_type>::value
template < typename ValueType, typename
std::enable_if <
not std::is_pointer<ValueType>::value
and not std::is_same<ValueType, typename string_t::value_type>::value
#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif
, int>::type = 0>
, int >::type = 0 >
operator ValueType() const
{
// delegate the call to get<>() const
@ -7390,17 +7393,17 @@ class basic_json
/*!
@brief static_cast between two types and indicate if it results in error
This function performs a static_cast between @a source and @a dest. It
This function performs a static_cast between @a source and @a dest. It
then checks if a static_cast back to @a dest produces an error.
@param[in] source the value to cast from
@param[in] source the value to cast from
@param[out] dest the value to cast to
@return @a true if the cast was performed without error, @a false otherwise
*/
template <typename T_A, typename T_B>
bool attempt_cast(T_A source, T_B & dest) const
bool attempt_cast(T_A source, T_B& dest) const
{
dest = static_cast<T_B>(source);
return (source == static_cast<T_A>(dest));
@ -7409,74 +7412,101 @@ class basic_json
/*!
@brief return number value for number tokens
This function translates the last token into the most appropriate
number type (either integer, unsigned integer or floating point),
which is passed back to the caller via the result parameter. The pointer
@a m_start points to the beginning of the parsed number. We first examine
This function translates the last token into the most appropriate
number type (either integer, unsigned integer or floating point), which
is passed back to the caller via the result parameter. The pointer @a
m_start points to the beginning of the parsed number. We first examine
the first character to determine the sign of the number and then pass
this pointer to either @a std::strtoull (if positive) or @a std::strtoll
(if negative), both of which set @a endptr to the first character past the
converted number. If this pointer is not the same as @a m_cursor, then
either more or less characters have been used during the comparison.
This can happen for inputs like "01" which will be treated like number 0
followed by number 1. This will also occur for valid floating point
inputs like "12e3" will be incorrectly read as 12. Numbers that are too
this pointer to either @a std::strtoull (if positive) or @a
std::strtoll (if negative), both of which set @a endptr to the first
character past the converted number. If this pointer is not the same as
@a m_cursor, then either more or less characters have been used during
the comparison.
This can happen for inputs like "01" which will be treated like number
0 followed by number 1. This will also occur for valid floating point
inputs like "12e3" will be incorrectly read as 12. Numbers that are too
large or too small for a signed/unsigned long long will cause a range
error (@a errno set to ERANGE). The parsed number is cast to a @ref
number_integer_t/@ref number_unsigned_t using the helper function @ref attempt_cast,
which returns @a false if the cast could not be peformed without error.
number_integer_t/@ref number_unsigned_t using the helper function @ref
attempt_cast, which returns @a false if the cast could not be peformed
without error.
In any of these cases (more/less characters read, range error or a cast
error) the pointer is passed to @a std:strtod, which also sets @a endptr to the
first character past the converted number. The resulting @ref number_float_t
is then cast to a @ref number_integer_t/@ref number_unsigned_t using
@ref attempt_cast and if no error occurs is stored in that form, otherwise
it is stored as a @ref number_float_t.
A final comparison is made of @a endptr and if still not the same as
@ref m_cursor a bad input is assumed and @a result parameter is set to NAN.
error) the pointer is passed to @a std:strtod, which also sets @a
endptr to the first character past the converted number. The resulting
@ref number_float_t is then cast to a @ref number_integer_t/@ref
number_unsigned_t using @ref attempt_cast and if no error occurs is
stored in that form, otherwise it is stored as a @ref number_float_t.
@param[out] result @ref basic_json object to receive the number, or NAN if the
conversion read past the current token. The latter case needs to be
treated by the caller function.
A final comparison is made of @a endptr and if still not the same as
@ref m_cursor a bad input is assumed and @a result parameter is set to
NAN.
@param[out] result @ref basic_json object to receive the number, or NAN
if the conversion read past the current token. The latter case needs to
be treated by the caller function.
*/
void get_number(basic_json& result) const
{
typename string_t::value_type* endptr;
assert(m_start != nullptr);
errno = 0;
// Attempt to parse it as an integer - first checking for a negative number
// attempt to parse it as an integer - first checking for a
// negative number
if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
{
// Positive, parse with strtoull and attempt cast to number_unsigned_t
if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr, 10), result.m_value.number_unsigned))
// positive, parse with strtoull and attempt cast to
// number_unsigned_t
if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
10), result.m_value.number_unsigned))
{
result.m_type = value_t::number_unsigned;
else result.m_type = value_t::number_float; // Cast failed due to overflow - store as float
}
else
{
// cast failed due to overflow - store as float
result.m_type = value_t::number_float;
}
}
else
{
// Negative, parse with strtoll and attempt cast to number_integer_t
if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr, 10), result.m_value.number_unsigned))
// Negative, parse with strtoll and attempt cast to
// number_integer_t
if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
10), result.m_value.number_unsigned))
{
result.m_type = value_t::number_integer;
else result.m_type = value_t::number_float; // Cast failed due to overflow - store as float
}
else
{
// cast failed due to overflow - store as float
result.m_type = value_t::number_float;
}
}
// Check the end of the number was reached and no range error occurred
if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE) result.m_type = value_t::number_float;
// check the end of the number was reached and no range error
// occurred
if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
{
result.m_type = value_t::number_float;
}
if (result.m_type == value_t::number_float)
{
// Either the number won't fit in an integer (range error from strtoull/strtoll or overflow on cast) or there was
// something else after the number, which could be an exponent
// Parse with strtod
// either the number won't fit in an integer (range error from
// strtoull/strtoll or overflow on cast) or there was something
// else after the number, which could be an exponent
// parse with strtod
result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
// Anything after the number is an error
if(reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
// anything after the number is an error
if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
{
throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
}
}
}
@ -7848,5 +7878,3 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t)
#endif
#endif

View File

@ -924,7 +924,8 @@ TEST_CASE("constructors")
SECTION("object with error")
{
CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), std::logic_error);
CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
std::logic_error);
CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
"cannot create object from initializer list");
}
@ -2312,7 +2313,7 @@ TEST_CASE("value conversion")
json::number_integer_t n = j.get<json::number_integer_t>();
CHECK(json(n) == j);
}
SECTION("number_unsigned_t")
{
json::number_unsigned_t n = j_unsigned.get<json::number_unsigned_t>();
@ -3665,7 +3666,7 @@ TEST_CASE("element access")
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
}
SECTION("number (unsigned)")
{
json j_nonobject(json::value_t::number_unsigned);
@ -3675,7 +3676,7 @@ TEST_CASE("element access")
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
}
SECTION("number (floating-point)")
{
json j_nonobject(json::value_t::number_float);
@ -5435,7 +5436,7 @@ TEST_CASE("iterators")
SECTION("object")
{
json j = {{"A", 1},{"B", 2},{"C", 3}};
json j = {{"A", 1}, {"B", 2}, {"C", 3}};
json j_const(j);
SECTION("json + begin/end")
@ -9661,7 +9662,7 @@ TEST_CASE("parser class")
// (2**53)-1
CHECK(json::parser("9007199254740991").parse().get<int64_t>() == 9007199254740991);
}
SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
{
// While RFC7159, Section 6 specifies a preference for support
@ -9672,7 +9673,7 @@ TEST_CASE("parser class")
// i.e. -(2**63) -> (2**64)-1.
// -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1))
CHECK(json::parser("-9223372036854775808").parse().get<int64_t>() == -9223372036854775807-1);
CHECK(json::parser("-9223372036854775808").parse().get<int64_t>() == -9223372036854775807 - 1);
// (2**63)-1
CHECK(json::parser("9223372036854775807").parse().get<int64_t>() == 9223372036854775807);
// (2**64)-1
@ -9720,12 +9721,14 @@ TEST_CASE("parser class")
CHECK_THROWS_WITH(json::parser("01").parse(), "parse error - 0 is not a number");
CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'");
CHECK_THROWS_WITH(json::parser("1.").parse(), "parse error - unexpected '.'; expected end of input");
CHECK_THROWS_WITH(json::parser("1.").parse(),
"parse error - unexpected '.'; expected end of input");
CHECK_THROWS_WITH(json::parser("1E").parse(),
"parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_WITH(json::parser("1E-").parse(),
"parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_WITH(json::parser("1.E1").parse(), "parse error - unexpected '.'; expected end of input");
CHECK_THROWS_WITH(json::parser("1.E1").parse(),
"parse error - unexpected '.'; expected end of input");
CHECK_THROWS_WITH(json::parser("-1E").parse(),
"parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_WITH(json::parser("-0E#").parse(),
@ -9767,7 +9770,8 @@ TEST_CASE("parser class")
CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument);
CHECK_THROWS_WITH(json::parser("0.").parse(), "parse error - unexpected '.'; expected end of input");
CHECK_THROWS_WITH(json::parser("0.").parse(),
"parse error - unexpected '.'; expected end of input");
CHECK_THROWS_WITH(json::parser("-").parse(), "parse error - unexpected '-'");
CHECK_THROWS_WITH(json::parser("--").parse(),
"parse error - unexpected '-'");
@ -12076,14 +12080,15 @@ TEST_CASE("regression tests")
SECTION("issue #89 - nonstandard integer type")
{
// create JSON class with nonstandard integer number type
using custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
using custom_json =
nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
custom_json j;
j["int_1"] = 1;
// we need to cast to int to compile with Catch - the value is int32_t
CHECK(static_cast<int>(j["int_1"]) == 1);
// tests for correct handling of non-standard integers that overflow the type selected by the user
// unsigned integer object creation - expected to wrap and still be stored as an integer
j = 4294967296U; // 2^32
CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
@ -12201,11 +12206,11 @@ TEST_CASE("regression tests")
{
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
}
SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
{
json j;
// Non-const access with key as "char []"
char array_key[] = "Key1";
CHECK_NOTHROW(j[array_key] = 1);
@ -12281,15 +12286,18 @@ TEST_CASE("regression tests")
// create JSON class with nonstandard float number type
// float
nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float = 1.23e25f;
nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float =
1.23e25f;
CHECK(j_float.get<float>() == 1.23e25f);
// double
nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double = 1.23e35f;
nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double =
1.23e35f;
CHECK(j_double.get<double>() == 1.23e35f);
// long double
nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double> j_long_double = 1.23e45L;
nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
j_long_double = 1.23e45L;
CHECK(j_long_double.get<long double>() == 1.23e45L);
}
}