Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
855cdcf0
Unverified
Commit
855cdcf0
authored
Mar 12, 2017
by
Niels Lohmann
Browse files
Options
Browse Files
Download
Plain Diff
🔀
merge branch 'develop' into feature/exceptions_3.0.0
parents
28dbe4e6
8feaf8dc
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
223 additions
and
84 deletions
+223
-84
json.hpp
src/json.hpp
+48
-32
json.hpp.re2c
src/json.hpp.re2c
+48
-32
unit-cbor.cpp
test/src/unit-cbor.cpp
+9
-5
unit-class_parser.cpp
test/src/unit-class_parser.cpp
+3
-1
unit-constructor1.cpp
test/src/unit-constructor1.cpp
+9
-3
unit-msgpack.cpp
test/src/unit-msgpack.cpp
+3
-3
unit-regression.cpp
test/src/unit-regression.cpp
+83
-2
unit-testsuites.cpp
test/src/unit-testsuites.cpp
+20
-6
No files found.
src/json.hpp
View file @
855cdcf0
...
@@ -468,16 +468,8 @@ struct external_constructor<value_t::number_float>
...
@@ -468,16 +468,8 @@ struct external_constructor<value_t::number_float>
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_float_t
val
)
noexcept
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_float_t
val
)
noexcept
{
{
// replace infinity and NAN by null
if
(
not
std
::
isfinite
(
val
))
{
j
=
BasicJsonType
{};
}
else
{
j
.
m_type
=
value_t
::
number_float
;
j
.
m_type
=
value_t
::
number_float
;
j
.
m_value
=
val
;
j
.
m_value
=
val
;
}
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
};
};
...
@@ -904,22 +896,15 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
...
@@ -904,22 +896,15 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
}
}
// forward_list doesn't have an insert method
// forward_list doesn't have an insert method
template
<
typename
BasicJsonType
,
typename
T
,
typename
Allocator
>
template
<
typename
BasicJsonType
,
typename
T
,
typename
Allocator
,
enable_if_t
<
std
::
is_convertible
<
BasicJsonType
,
T
>::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
std
::
forward_list
<
T
,
Allocator
>&
l
)
void
from_json
(
const
BasicJsonType
&
j
,
std
::
forward_list
<
T
,
Allocator
>&
l
)
{
{
// do not perform the check when user wants to retrieve jsons
// (except when it's null.. ?)
if
(
j
.
is_null
())
{
JSON_THROW
(
type_error
(
302
,
"type must be array, but is "
+
j
.
type_name
()));
}
if
(
not
std
::
is_same
<
T
,
BasicJsonType
>::
value
)
{
if
(
not
j
.
is_array
())
if
(
not
j
.
is_array
())
{
{
JSON_THROW
(
type_error
(
302
,
"type must be array, but is "
+
j
.
type_name
()));
JSON_THROW
(
type_error
(
302
,
"type must be array, but is "
+
j
.
type_name
()));
}
}
}
for
(
auto
it
=
j
.
rbegin
(),
end
=
j
.
rend
();
it
!=
end
;
++
it
)
for
(
auto
it
=
j
.
rbegin
(),
end
=
j
.
rend
();
it
!=
end
;
++
it
)
{
{
l
.
push_front
(
it
->
template
get
<
T
>
());
l
.
push_front
(
it
->
template
get
<
T
>
());
...
@@ -951,8 +936,8 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
...
@@ -951,8 +936,8 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
using
std
::
end
;
using
std
::
end
;
arr
.
reserve
(
j
.
size
());
arr
.
reserve
(
j
.
size
());
std
::
transform
(
std
::
transform
(
j
.
begin
(),
j
.
end
(),
j
.
begin
(),
j
.
end
(),
std
::
inserter
(
arr
,
end
(
arr
)),
[](
const
BasicJsonType
&
i
)
std
::
inserter
(
arr
,
end
(
arr
)),
[](
const
BasicJsonType
&
i
)
{
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
// method when value_type is BasicJsonType
...
@@ -962,22 +947,15 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
...
@@ -962,22 +947,15 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
enable_if_t
<
is_compatible_array_type
<
BasicJsonType
,
CompatibleArrayType
>::
value
and
enable_if_t
<
is_compatible_array_type
<
BasicJsonType
,
CompatibleArrayType
>::
value
and
std
::
is_convertible
<
BasicJsonType
,
typename
CompatibleArrayType
::
value_type
>::
value
and
not
std
::
is_same
<
typename
BasicJsonType
::
array_t
,
CompatibleArrayType
>::
value
,
int
>
=
0
>
not
std
::
is_same
<
typename
BasicJsonType
::
array_t
,
CompatibleArrayType
>::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
)
void
from_json
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
)
{
{
if
(
j
.
is_null
())
{
JSON_THROW
(
type_error
(
302
,
"type must be array, but is "
+
j
.
type_name
()));
}
// when T == BasicJsonType, do not check if value_t is correct
if
(
not
std
::
is_same
<
typename
CompatibleArrayType
::
value_type
,
BasicJsonType
>::
value
)
{
if
(
not
j
.
is_array
())
if
(
not
j
.
is_array
())
{
{
JSON_THROW
(
type_error
(
302
,
"type must be array, but is "
+
j
.
type_name
()));
JSON_THROW
(
type_error
(
302
,
"type must be array, but is "
+
j
.
type_name
()));
}
}
}
from_json_array_impl
(
j
,
arr
,
priority_tag
<
1
>
{});
from_json_array_impl
(
j
,
arr
,
priority_tag
<
1
>
{});
}
}
...
@@ -6916,6 +6894,13 @@ class basic_json
...
@@ -6916,6 +6894,13 @@ class basic_json
*/
*/
void
dump_float
(
number_float_t
x
)
void
dump_float
(
number_float_t
x
)
{
{
// NaN / inf
if
(
not
std
::
isfinite
(
x
)
or
std
::
isnan
(
x
))
{
o
.
write
(
"null"
,
4
);
return
;
}
// special case for 0.0 and -0.0
// special case for 0.0 and -0.0
if
(
x
==
0
)
if
(
x
==
0
)
{
{
...
@@ -8021,6 +8006,35 @@ class basic_json
...
@@ -8021,6 +8006,35 @@ class basic_json
}
}
/*!
/*!
@brief check if the next byte belongs to a string
While parsing a map, the keys must be strings. This function checks if the
current byte is one of the start bytes for a string in MessagePack:
- 0xa0 - 0xbf: fixstr
- 0xd9: str 8
- 0xda: str 16
- 0xdb: str 32
@param[in] v MessagePack serialization
@param[in] idx byte index in @a v to check for a string
@throw std::invalid_argument if `v[idx]` does not belong to a string
*/
static
void
msgpack_expect_string
(
const
std
::
vector
<
uint8_t
>&
v
,
size_t
idx
)
{
check_length
(
v
.
size
(),
1
,
idx
);
const
auto
byte
=
v
[
idx
];
if
((
byte
>=
0xa0
and
byte
<=
0xbf
)
or
(
byte
>=
0xd9
and
byte
<=
0xdb
))
{
return
;
}
JSON_THROW
(
std
::
invalid_argument
(
"error parsing a msgpack string @ "
+
std
::
to_string
(
idx
)
+
": "
+
std
::
to_string
(
static_cast
<
int
>
(
v
[
idx
]))));
}
/*!
@brief create a JSON value from a given MessagePack vector
@brief create a JSON value from a given MessagePack vector
@param[in] v MessagePack serialization
@param[in] v MessagePack serialization
...
@@ -8054,6 +8068,7 @@ class basic_json
...
@@ -8054,6 +8068,7 @@ class basic_json
const
size_t
len
=
v
[
current_idx
]
&
0x0f
;
const
size_t
len
=
v
[
current_idx
]
&
0x0f
;
for
(
size_t
i
=
0
;
i
<
len
;
++
i
)
for
(
size_t
i
=
0
;
i
<
len
;
++
i
)
{
{
msgpack_expect_string
(
v
,
idx
);
std
::
string
key
=
from_msgpack_internal
(
v
,
idx
);
std
::
string
key
=
from_msgpack_internal
(
v
,
idx
);
result
[
key
]
=
from_msgpack_internal
(
v
,
idx
);
result
[
key
]
=
from_msgpack_internal
(
v
,
idx
);
}
}
...
@@ -8233,6 +8248,7 @@ class basic_json
...
@@ -8233,6 +8248,7 @@ class basic_json
idx
+=
2
;
// skip 2 size bytes
idx
+=
2
;
// skip 2 size bytes
for
(
size_t
i
=
0
;
i
<
len
;
++
i
)
for
(
size_t
i
=
0
;
i
<
len
;
++
i
)
{
{
msgpack_expect_string
(
v
,
idx
);
std
::
string
key
=
from_msgpack_internal
(
v
,
idx
);
std
::
string
key
=
from_msgpack_internal
(
v
,
idx
);
result
[
key
]
=
from_msgpack_internal
(
v
,
idx
);
result
[
key
]
=
from_msgpack_internal
(
v
,
idx
);
}
}
...
@@ -8246,6 +8262,7 @@ class basic_json
...
@@ -8246,6 +8262,7 @@ class basic_json
idx
+=
4
;
// skip 4 size bytes
idx
+=
4
;
// skip 4 size bytes
for
(
size_t
i
=
0
;
i
<
len
;
++
i
)
for
(
size_t
i
=
0
;
i
<
len
;
++
i
)
{
{
msgpack_expect_string
(
v
,
idx
);
std
::
string
key
=
from_msgpack_internal
(
v
,
idx
);
std
::
string
key
=
from_msgpack_internal
(
v
,
idx
);
result
[
key
]
=
from_msgpack_internal
(
v
,
idx
);
result
[
key
]
=
from_msgpack_internal
(
v
,
idx
);
}
}
...
@@ -11697,11 +11714,10 @@ basic_json_parser_74:
...
@@ -11697,11 +11714,10 @@ basic_json_parser_74:
result
.
m_type
=
value_t
::
number_float
;
result
.
m_type
=
value_t
::
number_float
;
result
.
m_value
=
val
;
result
.
m_value
=
val
;
//
replace infinity and NAN by null
//
throw in case of infinity or NAN
if
(
not
std
::
isfinite
(
result
.
m_value
.
number_float
))
if
(
not
std
::
isfinite
(
result
.
m_value
.
number_float
))
{
{
result
.
m_type
=
value_t
::
null
;
JSON_THROW
(
std
::
out_of_range
(
"number overflow: "
+
get_token_string
()));
result
.
m_value
=
basic_json
::
json_value
();
}
}
return
true
;
return
true
;
...
...
src/json.hpp.re2c
View file @
855cdcf0
...
@@ -468,16 +468,8 @@ struct external_constructor<value_t::number_float>
...
@@ -468,16 +468,8 @@ struct external_constructor<value_t::number_float>
template<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
{
{
// replace infinity and NAN by null
if (not std::isfinite(val))
{
j = BasicJsonType{};
}
else
{
j.m_type = value_t::number_float;
j.m_type = value_t::number_float;
j.m_value = val;
j.m_value = val;
}
j.assert_invariant();
j.assert_invariant();
}
}
};
};
...
@@ -904,22 +896,15 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
...
@@ -904,22 +896,15 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
}
}
// forward_list doesn't have an insert method
// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator>
template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
{
// do not perform the check when user wants to retrieve jsons
// (except when it's null.. ?)
if (j.is_null())
{
JSON_THROW(type_error(302, "type must be array, but is " + j.type_name()));
}
if (not std::is_same<T, BasicJsonType>::value)
{
if (not j.is_array())
if (not j.is_array())
{
{
JSON_THROW(type_error(302, "type must be array, but is " + j.type_name()));
JSON_THROW(type_error(302, "type must be array, but is " + j.type_name()));
}
}
}
for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
{
{
l.push_front(it->template get<T>());
l.push_front(it->template get<T>());
...
@@ -951,8 +936,8 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
...
@@ -951,8 +936,8 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
using std::end;
using std::end;
arr.reserve(j.size());
arr.reserve(j.size());
std::transform(
std::transform(
j.begin(), j.end(),
j.begin(), j.end(),
std::inserter(arr, end(arr)), [](const BasicJsonType & i)
std::inserter(arr, end(arr)), [](const BasicJsonType & i)
{
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
// method when value_type is BasicJsonType
...
@@ -962,22 +947,15 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
...
@@ -962,22 +947,15 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
template<typename BasicJsonType, typename CompatibleArrayType,
template<typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
std::is_convertible<BasicJsonType, typename CompatibleArrayType::value_type>::value and
not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
{
{
if (j.is_null())
{
JSON_THROW(type_error(302, "type must be array, but is " + j.type_name()));
}
// when T == BasicJsonType, do not check if value_t is correct
if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
{
if (not j.is_array())
if (not j.is_array())
{
{
JSON_THROW(type_error(302, "type must be array, but is " + j.type_name()));
JSON_THROW(type_error(302, "type must be array, but is " + j.type_name()));
}
}
}
from_json_array_impl(j, arr, priority_tag<1> {});
from_json_array_impl(j, arr, priority_tag<1> {});
}
}
...
@@ -6916,6 +6894,13 @@ class basic_json
...
@@ -6916,6 +6894,13 @@ class basic_json
*/
*/
void dump_float(number_float_t x)
void dump_float(number_float_t x)
{
{
// NaN / inf
if (not std::isfinite(x) or std::isnan(x))
{
o.write("null", 4);
return;
}
// special case for 0.0 and -0.0
// special case for 0.0 and -0.0
if (x == 0)
if (x == 0)
{
{
...
@@ -8021,6 +8006,35 @@ class basic_json
...
@@ -8021,6 +8006,35 @@ class basic_json
}
}
/*!
/*!
@brief check if the next byte belongs to a string
While parsing a map, the keys must be strings. This function checks if the
current byte is one of the start bytes for a string in MessagePack:
- 0xa0 - 0xbf: fixstr
- 0xd9: str 8
- 0xda: str 16
- 0xdb: str 32
@param[in] v MessagePack serialization
@param[in] idx byte index in @a v to check for a string
@throw std::invalid_argument if `v[idx]` does not belong to a string
*/
static void msgpack_expect_string(const std::vector<uint8_t>& v, size_t idx)
{
check_length(v.size(), 1, idx);
const auto byte = v[idx];
if ((byte >= 0xa0 and byte <= 0xbf) or (byte >= 0xd9 and byte <= 0xdb))
{
return;
}
JSON_THROW(std::invalid_argument("error parsing a msgpack string @ " + std::to_string(idx) + ": " + std::to_string(static_cast<int>(v[idx]))));
}
/*!
@brief create a JSON value from a given MessagePack vector
@brief create a JSON value from a given MessagePack vector
@param[in] v MessagePack serialization
@param[in] v MessagePack serialization
...
@@ -8054,6 +8068,7 @@ class basic_json
...
@@ -8054,6 +8068,7 @@ class basic_json
const size_t len = v[current_idx] & 0x0f;
const size_t len = v[current_idx] & 0x0f;
for (size_t i = 0; i < len; ++i)
for (size_t i = 0; i < len; ++i)
{
{
msgpack_expect_string(v, idx);
std::string key = from_msgpack_internal(v, idx);
std::string key = from_msgpack_internal(v, idx);
result[key] = from_msgpack_internal(v, idx);
result[key] = from_msgpack_internal(v, idx);
}
}
...
@@ -8233,6 +8248,7 @@ class basic_json
...
@@ -8233,6 +8248,7 @@ class basic_json
idx += 2; // skip 2 size bytes
idx += 2; // skip 2 size bytes
for (size_t i = 0; i < len; ++i)
for (size_t i = 0; i < len; ++i)
{
{
msgpack_expect_string(v, idx);
std::string key = from_msgpack_internal(v, idx);
std::string key = from_msgpack_internal(v, idx);
result[key] = from_msgpack_internal(v, idx);
result[key] = from_msgpack_internal(v, idx);
}
}
...
@@ -8246,6 +8262,7 @@ class basic_json
...
@@ -8246,6 +8262,7 @@ class basic_json
idx += 4; // skip 4 size bytes
idx += 4; // skip 4 size bytes
for (size_t i = 0; i < len; ++i)
for (size_t i = 0; i < len; ++i)
{
{
msgpack_expect_string(v, idx);
std::string key = from_msgpack_internal(v, idx);
std::string key = from_msgpack_internal(v, idx);
result[key] = from_msgpack_internal(v, idx);
result[key] = from_msgpack_internal(v, idx);
}
}
...
@@ -10730,11 +10747,10 @@ class basic_json
...
@@ -10730,11 +10747,10 @@ class basic_json
result.m_type = value_t::number_float;
result.m_type = value_t::number_float;
result.m_value = val;
result.m_value = val;
//
replace infinity and NAN by null
//
throw in case of infinity or NAN
if (not std::isfinite(result.m_value.number_float))
if (not std::isfinite(result.m_value.number_float))
{
{
result.m_type = value_t::null;
JSON_THROW(std::out_of_range("number overflow: " + get_token_string()));
result.m_value = basic_json::json_value();
}
}
return true;
return true;
...
...
test/src/unit-cbor.cpp
View file @
855cdcf0
...
@@ -744,13 +744,17 @@ TEST_CASE("CBOR")
...
@@ -744,13 +744,17 @@ TEST_CASE("CBOR")
SECTION
(
"infinity"
)
SECTION
(
"infinity"
)
{
{
json
j
=
json
::
from_cbor
(
std
::
vector
<
uint8_t
>
({
0xf9
,
0x7c
,
0x00
}));
json
j
=
json
::
from_cbor
(
std
::
vector
<
uint8_t
>
({
0xf9
,
0x7c
,
0x00
}));
CHECK
(
j
==
nullptr
);
json
::
number_float_t
d
=
j
;
CHECK
(
not
std
::
isfinite
(
d
));
CHECK
(
j
.
dump
()
==
"null"
);
}
}
SECTION
(
"NaN"
)
SECTION
(
"NaN"
)
{
{
json
j
=
json
::
from_cbor
(
std
::
vector
<
uint8_t
>
({
0xf9
,
0x7c
,
0x01
}));
json
j
=
json
::
from_cbor
(
std
::
vector
<
uint8_t
>
({
0xf9
,
0x7c
,
0x01
}));
CHECK
(
j
==
nullptr
);
json
::
number_float_t
d
=
j
;
CHECK
(
std
::
isnan
(
d
));
CHECK
(
j
.
dump
()
==
"null"
);
}
}
}
}
}
}
...
@@ -1430,7 +1434,7 @@ TEST_CASE("CBOR roundtrips", "[hide]")
...
@@ -1430,7 +1434,7 @@ TEST_CASE("CBOR roundtrips", "[hide]")
"test/data/nst_json_testsuite/test_parsing/y_number_after_space.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_after_space.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json"
,
//
"test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
"test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json"
,
...
@@ -1442,9 +1446,9 @@ TEST_CASE("CBOR roundtrips", "[hide]")
...
@@ -1442,9 +1446,9 @@ TEST_CASE("CBOR roundtrips", "[hide]")
"test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json"
,
//
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json"
,
//
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
"test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json"
,
...
...
test/src/unit-class_parser.cpp
View file @
855cdcf0
...
@@ -276,7 +276,9 @@ TEST_CASE("parser class")
...
@@ -276,7 +276,9 @@ TEST_CASE("parser class")
SECTION
(
"overflow"
)
SECTION
(
"overflow"
)
{
{
CHECK
(
json
::
parser
(
"1.18973e+4932"
).
parse
()
==
json
());
// overflows during parsing yield an exception
CHECK_THROWS_AS
(
json
::
parser
(
"1.18973e+4932"
).
parse
()
==
json
(),
std
::
out_of_range
);
CHECK_THROWS_WITH
(
json
::
parser
(
"1.18973e+4932"
).
parse
()
==
json
(),
"number overflow: 1.18973e+4932"
);
}
}
SECTION
(
"invalid numbers"
)
SECTION
(
"invalid numbers"
)
...
...
test/src/unit-constructor1.cpp
View file @
855cdcf0
...
@@ -702,11 +702,17 @@ TEST_CASE("constructors")
...
@@ -702,11 +702,17 @@ TEST_CASE("constructors")
SECTION
(
"infinity"
)
SECTION
(
"infinity"
)
{
{
// infinity is stored as null
// infinity is stored properly, but serialized to null
// should change in the future: https://github.com/nlohmann/json/issues/388
json
::
number_float_t
n
(
std
::
numeric_limits
<
json
::
number_float_t
>::
infinity
());
json
::
number_float_t
n
(
std
::
numeric_limits
<
json
::
number_float_t
>::
infinity
());
json
j
(
n
);
json
j
(
n
);
CHECK
(
j
.
type
()
==
json
::
value_t
::
null
);
CHECK
(
j
.
type
()
==
json
::
value_t
::
number_float
);
// check round trip of infinity
json
::
number_float_t
d
=
j
;
CHECK
(
d
==
n
);
// check that inf is serialized to null
CHECK
(
j
.
dump
()
==
"null"
);
}
}
}
}
...
...
test/src/unit-msgpack.cpp
View file @
855cdcf0
...
@@ -1200,7 +1200,7 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
...
@@ -1200,7 +1200,7 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
"test/data/nst_json_testsuite/test_parsing/y_number_after_space.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_after_space.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json"
,
//
"test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
"test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json"
,
...
@@ -1212,9 +1212,9 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
...
@@ -1212,9 +1212,9 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
"test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json"
,
//
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json"
,
//
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
"test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json"
,
...
...
test/src/unit-regression.cpp
View file @
855cdcf0
...
@@ -32,6 +32,7 @@ SOFTWARE.
...
@@ -32,6 +32,7 @@ SOFTWARE.
using
nlohmann
::
json
;
using
nlohmann
::
json
;
#include <fstream>
#include <fstream>
#include <list>
TEST_CASE
(
"regression tests"
)
TEST_CASE
(
"regression tests"
)
{
{
...
@@ -48,6 +49,7 @@ TEST_CASE("regression tests")
...
@@ -48,6 +49,7 @@ TEST_CASE("regression tests")
SECTION
(
"issue #70 - Handle infinity and NaN cases"
)
SECTION
(
"issue #70 - Handle infinity and NaN cases"
)
{
{
/*
SECTION("NAN value")
SECTION("NAN value")
{
{
CHECK(json(NAN) == json());
CHECK(json(NAN) == json());
...
@@ -59,6 +61,36 @@ TEST_CASE("regression tests")
...
@@ -59,6 +61,36 @@ TEST_CASE("regression tests")
CHECK(json(INFINITY) == json());
CHECK(json(INFINITY) == json());
CHECK(json(json::number_float_t(INFINITY)) == json());
CHECK(json(json::number_float_t(INFINITY)) == json());
}
}
*/
// With 3.0.0, the semantics of this changed: NAN and infinity are
// stored properly inside the JSON value (no exception or conversion
// to null), but are serialized as null.
SECTION
(
"NAN value"
)
{
json
j1
=
NAN
;
CHECK
(
j1
.
is_number_float
());
json
::
number_float_t
f1
=
j1
;
CHECK
(
std
::
isnan
(
f1
));
json
j2
=
json
::
number_float_t
(
NAN
);
CHECK
(
j2
.
is_number_float
());
json
::
number_float_t
f2
=
j2
;
CHECK
(
std
::
isnan
(
f2
));
}
SECTION
(
"infinity"
)
{
json
j1
=
INFINITY
;
CHECK
(
j1
.
is_number_float
());
json
::
number_float_t
f1
=
j1
;
CHECK
(
not
std
::
isfinite
(
f1
));
json
j2
=
json
::
number_float_t
(
INFINITY
);
CHECK
(
j2
.
is_number_float
());
json
::
number_float_t
f2
=
j2
;
CHECK
(
not
std
::
isfinite
(
f2
));
}
}
}
SECTION
(
"pull request #71 - handle enum type"
)
SECTION
(
"pull request #71 - handle enum type"
)
...
@@ -558,8 +590,8 @@ TEST_CASE("regression tests")
...
@@ -558,8 +590,8 @@ TEST_CASE("regression tests")
SECTION
(
"issue #329 - serialized value not always can be parsed"
)
SECTION
(
"issue #329 - serialized value not always can be parsed"
)
{
{
json
j
=
json
::
parse
(
"22e2222"
);
CHECK_THROWS_AS
(
json
::
parse
(
"22e2222"
),
std
::
out_of_range
);
CHECK
(
j
==
json
()
);
CHECK
_THROWS_WITH
(
json
::
parse
(
"22e2222"
),
"number overflow: 22e2222"
);
}
}
SECTION
(
"issue #366 - json::parse on failed stream gets stuck"
)
SECTION
(
"issue #366 - json::parse on failed stream gets stuck"
)
...
@@ -834,6 +866,55 @@ TEST_CASE("regression tests")
...
@@ -834,6 +866,55 @@ TEST_CASE("regression tests")
CHECK
(
s1
==
s2
);
CHECK
(
s1
==
s2
);
}
}
SECTION
(
"issue #473 - inconsistent behavior in conversion to array type"
)
{
json
j_array
=
{
1
,
2
,
3
,
4
};
json
j_number
=
42
;
json
j_null
=
nullptr
;
SECTION
(
"std::vector"
)
{
auto
create
=
[](
const
json
&
j
)
{
std
::
vector
<
int
>
v
=
j
;
};
CHECK_NOTHROW
(
create
(
j_array
));
CHECK_THROWS_AS
(
create
(
j_number
),
json
::
type_error
);
CHECK_THROWS_WITH
(
create
(
j_number
),
"[json.exception.type_error.302] type must be array, but is number"
);
CHECK_THROWS_AS
(
create
(
j_null
),
json
::
type_error
);
CHECK_THROWS_WITH
(
create
(
j_null
),
"[json.exception.type_error.302] type must be array, but is null"
);
}
SECTION
(
"std::list"
)
{
auto
create
=
[](
const
json
&
j
)
{
std
::
list
<
int
>
v
=
j
;
};
CHECK_NOTHROW
(
create
(
j_array
));
CHECK_THROWS_AS
(
create
(
j_number
),
json
::
type_error
);
CHECK_THROWS_WITH
(
create
(
j_number
),
"[json.exception.type_error.302] type must be array, but is number"
);
CHECK_THROWS_AS
(
create
(
j_null
),
json
::
type_error
);
CHECK_THROWS_WITH
(
create
(
j_null
),
"[json.exception.type_error.302] type must be array, but is null"
);
}
SECTION
(
"std::forward_list"
)
{
auto
create
=
[](
const
json
&
j
)
{
std
::
forward_list
<
int
>
v
=
j
;
};
CHECK_NOTHROW
(
create
(
j_array
));
CHECK_THROWS_AS
(
create
(
j_number
),
json
::
type_error
);
CHECK_THROWS_WITH
(
create
(
j_number
),
"[json.exception.type_error.302] type must be array, but is number"
);
CHECK_THROWS_AS
(
create
(
j_null
),
json
::
type_error
);
CHECK_THROWS_WITH
(
create
(
j_null
),
"[json.exception.type_error.302] type must be array, but is null"
);
}
}
SECTION
(
"issue #486 - json::value_t can't be a map's key type in VC++ 2015"
)
SECTION
(
"issue #486 - json::value_t can't be a map's key type in VC++ 2015"
)
{
{
// the code below must compile with MSVC
// the code below must compile with MSVC
...
...
test/src/unit-testsuites.cpp
View file @
855cdcf0
...
@@ -460,7 +460,6 @@ TEST_CASE("nst's JSONTestSuite")
...
@@ -460,7 +460,6 @@ TEST_CASE("nst's JSONTestSuite")
"test/data/nst_json_testsuite/test_parsing/y_number_after_space.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_after_space.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json"
,
...
@@ -472,9 +471,7 @@ TEST_CASE("nst's JSONTestSuite")
...
@@ -472,9 +471,7 @@ TEST_CASE("nst's JSONTestSuite")
"test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json"
,
...
@@ -765,9 +762,6 @@ TEST_CASE("nst's JSONTestSuite")
...
@@ -765,9 +762,6 @@ TEST_CASE("nst's JSONTestSuite")
{
{
for
(
auto
filename
:
for
(
auto
filename
:
{
{
// we currently do not limit exponents
"test/data/nst_json_testsuite/test_parsing/i_number_neg_int_huge_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/i_number_pos_double_huge_exp.json"
,
// we do not pose a limit on nesting
// we do not pose a limit on nesting
"test/data/nst_json_testsuite/test_parsing/i_structure_500_nested_arrays.json"
,
"test/data/nst_json_testsuite/test_parsing/i_structure_500_nested_arrays.json"
,
// we silently ignore BOMs
// we silently ignore BOMs
...
@@ -787,6 +781,26 @@ TEST_CASE("nst's JSONTestSuite")
...
@@ -787,6 +781,26 @@ TEST_CASE("nst's JSONTestSuite")
}
}
}
}
// numbers that overflow during parsing
SECTION
(
"i/y -> n (out of range)"
)
{
for
(
auto
filename
:
{
"test/data/nst_json_testsuite/test_parsing/i_number_neg_int_huge_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/i_number_pos_double_huge_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json"
,
"test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json"
}
)
{
CAPTURE
(
filename
);
std
::
ifstream
f
(
filename
);
json
j
;
CHECK_THROWS_AS
(
j
<<
f
,
std
::
out_of_range
);
}
}
SECTION
(
"i -> n"
)
SECTION
(
"i -> n"
)
{
{
for
(
auto
filename
:
for
(
auto
filename
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment