Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
ff57bdcc
Unverified
Commit
ff57bdcc
authored
Jan 10, 2021
by
Niels Lohmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
🐛
fix invariants
parent
9d0150c2
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
118 additions
and
60 deletions
+118
-60
include/nlohmann/detail/conversions/to_json.hpp
include/nlohmann/detail/conversions/to_json.hpp
+10
-0
include/nlohmann/detail/input/json_sax.hpp
include/nlohmann/detail/input/json_sax.hpp
+17
-16
include/nlohmann/detail/input/parser.hpp
include/nlohmann/detail/input/parser.hpp
+2
-2
include/nlohmann/json.hpp
include/nlohmann/json.hpp
+30
-12
single_include/nlohmann/json.hpp
single_include/nlohmann/json.hpp
+59
-30
No files found.
include/nlohmann/detail/conversions/to_json.hpp
View file @
ff57bdcc
...
@@ -132,6 +132,7 @@ struct external_constructor<value_t::array>
...
@@ -132,6 +132,7 @@ struct external_constructor<value_t::array>
{
{
j
.
m_type
=
value_t
::
array
;
j
.
m_type
=
value_t
::
array
;
j
.
m_value
=
arr
;
j
.
m_value
=
arr
;
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
...
@@ -140,6 +141,7 @@ struct external_constructor<value_t::array>
...
@@ -140,6 +141,7 @@ struct external_constructor<value_t::array>
{
{
j
.
m_type
=
value_t
::
array
;
j
.
m_type
=
value_t
::
array
;
j
.
m_value
=
std
::
move
(
arr
);
j
.
m_value
=
std
::
move
(
arr
);
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
...
@@ -152,6 +154,7 @@ struct external_constructor<value_t::array>
...
@@ -152,6 +154,7 @@ struct external_constructor<value_t::array>
using
std
::
end
;
using
std
::
end
;
j
.
m_type
=
value_t
::
array
;
j
.
m_type
=
value_t
::
array
;
j
.
m_value
.
array
=
j
.
template
create
<
typename
BasicJsonType
::
array_t
>(
begin
(
arr
),
end
(
arr
));
j
.
m_value
.
array
=
j
.
template
create
<
typename
BasicJsonType
::
array_t
>(
begin
(
arr
),
end
(
arr
));
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
...
@@ -164,6 +167,9 @@ struct external_constructor<value_t::array>
...
@@ -164,6 +167,9 @@ struct external_constructor<value_t::array>
for
(
const
bool
x
:
arr
)
for
(
const
bool
x
:
arr
)
{
{
j
.
m_value
.
array
->
push_back
(
x
);
j
.
m_value
.
array
->
push_back
(
x
);
#if JSON_DIAGNOSTICS
j
.
m_value
.
array
->
back
().
m_parent
=
&
j
;
#endif
}
}
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
...
@@ -179,6 +185,7 @@ struct external_constructor<value_t::array>
...
@@ -179,6 +185,7 @@ struct external_constructor<value_t::array>
{
{
std
::
copy
(
std
::
begin
(
arr
),
std
::
end
(
arr
),
j
.
m_value
.
array
->
begin
());
std
::
copy
(
std
::
begin
(
arr
),
std
::
end
(
arr
),
j
.
m_value
.
array
->
begin
());
}
}
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
};
};
...
@@ -191,6 +198,7 @@ struct external_constructor<value_t::object>
...
@@ -191,6 +198,7 @@ struct external_constructor<value_t::object>
{
{
j
.
m_type
=
value_t
::
object
;
j
.
m_type
=
value_t
::
object
;
j
.
m_value
=
obj
;
j
.
m_value
=
obj
;
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
...
@@ -199,6 +207,7 @@ struct external_constructor<value_t::object>
...
@@ -199,6 +207,7 @@ struct external_constructor<value_t::object>
{
{
j
.
m_type
=
value_t
::
object
;
j
.
m_type
=
value_t
::
object
;
j
.
m_value
=
std
::
move
(
obj
);
j
.
m_value
=
std
::
move
(
obj
);
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
...
@@ -211,6 +220,7 @@ struct external_constructor<value_t::object>
...
@@ -211,6 +220,7 @@ struct external_constructor<value_t::object>
j
.
m_type
=
value_t
::
object
;
j
.
m_type
=
value_t
::
object
;
j
.
m_value
.
object
=
j
.
template
create
<
typename
BasicJsonType
::
object_t
>(
begin
(
obj
),
end
(
obj
));
j
.
m_value
.
object
=
j
.
template
create
<
typename
BasicJsonType
::
object_t
>(
begin
(
obj
),
end
(
obj
));
j
.
set_parent
(
j
,
true
);
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
};
};
...
...
include/nlohmann/detail/input/json_sax.hpp
View file @
ff57bdcc
...
@@ -236,6 +236,7 @@ class json_sax_dom_parser
...
@@ -236,6 +236,7 @@ class json_sax_dom_parser
bool
end_object
()
bool
end_object
()
{
{
ref_stack
.
back
()
->
set_parent
(
*
ref_stack
.
back
(),
true
);
ref_stack
.
pop_back
();
ref_stack
.
pop_back
();
return
true
;
return
true
;
}
}
...
@@ -254,6 +255,7 @@ class json_sax_dom_parser
...
@@ -254,6 +255,7 @@ class json_sax_dom_parser
bool
end_array
()
bool
end_array
()
{
{
ref_stack
.
back
()
->
set_parent
(
*
ref_stack
.
back
(),
true
);
ref_stack
.
pop_back
();
ref_stack
.
pop_back
();
return
true
;
return
true
;
}
}
...
@@ -298,18 +300,12 @@ class json_sax_dom_parser
...
@@ -298,18 +300,12 @@ class json_sax_dom_parser
if
(
ref_stack
.
back
()
->
is_array
())
if
(
ref_stack
.
back
()
->
is_array
())
{
{
ref_stack
.
back
()
->
m_value
.
array
->
emplace_back
(
std
::
forward
<
Value
>
(
v
));
ref_stack
.
back
()
->
m_value
.
array
->
emplace_back
(
std
::
forward
<
Value
>
(
v
));
#if JSON_DIAGNOSTICS
ref_stack
.
back
()
->
m_value
.
array
->
back
().
m_parent
=
ref_stack
.
back
();
#endif
return
&
(
ref_stack
.
back
()
->
m_value
.
array
->
back
());
return
&
(
ref_stack
.
back
()
->
m_value
.
array
->
back
());
}
}
JSON_ASSERT
(
ref_stack
.
back
()
->
is_object
());
JSON_ASSERT
(
ref_stack
.
back
()
->
is_object
());
JSON_ASSERT
(
object_element
);
JSON_ASSERT
(
object_element
);
*
object_element
=
BasicJsonType
(
std
::
forward
<
Value
>
(
v
));
*
object_element
=
BasicJsonType
(
std
::
forward
<
Value
>
(
v
));
#if JSON_DIAGNOSTICS
object_element
->
m_parent
=
ref_stack
.
back
();
#endif
return
object_element
;
return
object_element
;
}
}
...
@@ -432,10 +428,17 @@ class json_sax_dom_callback_parser
...
@@ -432,10 +428,17 @@ class json_sax_dom_callback_parser
bool
end_object
()
bool
end_object
()
{
{
if
(
ref_stack
.
back
()
&&
!
callback
(
static_cast
<
int
>
(
ref_stack
.
size
())
-
1
,
parse_event_t
::
object_end
,
*
ref_stack
.
back
())
)
if
(
ref_stack
.
back
())
{
{
// discard object
if
(
!
callback
(
static_cast
<
int
>
(
ref_stack
.
size
())
-
1
,
parse_event_t
::
object_end
,
*
ref_stack
.
back
()))
*
ref_stack
.
back
()
=
discarded
;
{
// discard object
*
ref_stack
.
back
()
=
discarded
;
}
else
{
ref_stack
.
back
()
->
set_parent
(
*
ref_stack
.
back
(),
true
);
}
}
}
JSON_ASSERT
(
!
ref_stack
.
empty
());
JSON_ASSERT
(
!
ref_stack
.
empty
());
...
@@ -483,7 +486,11 @@ class json_sax_dom_callback_parser
...
@@ -483,7 +486,11 @@ class json_sax_dom_callback_parser
if
(
ref_stack
.
back
())
if
(
ref_stack
.
back
())
{
{
keep
=
callback
(
static_cast
<
int
>
(
ref_stack
.
size
())
-
1
,
parse_event_t
::
array_end
,
*
ref_stack
.
back
());
keep
=
callback
(
static_cast
<
int
>
(
ref_stack
.
size
())
-
1
,
parse_event_t
::
array_end
,
*
ref_stack
.
back
());
if
(
!
keep
)
if
(
keep
)
{
ref_stack
.
back
()
->
set_parent
(
*
ref_stack
.
back
(),
true
);
}
else
{
{
// discard array
// discard array
*
ref_stack
.
back
()
=
discarded
;
*
ref_stack
.
back
()
=
discarded
;
...
@@ -582,9 +589,6 @@ class json_sax_dom_callback_parser
...
@@ -582,9 +589,6 @@ class json_sax_dom_callback_parser
if
(
ref_stack
.
back
()
->
is_array
())
if
(
ref_stack
.
back
()
->
is_array
())
{
{
ref_stack
.
back
()
->
m_value
.
array
->
emplace_back
(
std
::
move
(
value
));
ref_stack
.
back
()
->
m_value
.
array
->
emplace_back
(
std
::
move
(
value
));
#if JSON_DIAGNOSTICS
ref_stack
.
back
()
->
m_value
.
array
->
back
().
m_parent
=
ref_stack
.
back
();
#endif
return
{
true
,
&
(
ref_stack
.
back
()
->
m_value
.
array
->
back
())};
return
{
true
,
&
(
ref_stack
.
back
()
->
m_value
.
array
->
back
())};
}
}
...
@@ -602,9 +606,6 @@ class json_sax_dom_callback_parser
...
@@ -602,9 +606,6 @@ class json_sax_dom_callback_parser
JSON_ASSERT
(
object_element
);
JSON_ASSERT
(
object_element
);
*
object_element
=
std
::
move
(
value
);
*
object_element
=
std
::
move
(
value
);
#if JSON_DIAGNOSTICS
object_element
->
m_parent
=
ref_stack
.
back
();
#endif
return
{
true
,
object_element
};
return
{
true
,
object_element
};
}
}
...
...
include/nlohmann/detail/input/parser.hpp
View file @
ff57bdcc
...
@@ -90,7 +90,6 @@ class parser
...
@@ -90,7 +90,6 @@ class parser
{
{
json_sax_dom_callback_parser
<
BasicJsonType
>
sdp
(
result
,
callback
,
allow_exceptions
);
json_sax_dom_callback_parser
<
BasicJsonType
>
sdp
(
result
,
callback
,
allow_exceptions
);
sax_parse_internal
(
&
sdp
);
sax_parse_internal
(
&
sdp
);
result
.
assert_invariant
();
// in strict mode, input must be completely read
// in strict mode, input must be completely read
if
(
strict
&&
(
get_token
()
!=
token_type
::
end_of_input
))
if
(
strict
&&
(
get_token
()
!=
token_type
::
end_of_input
))
...
@@ -119,7 +118,6 @@ class parser
...
@@ -119,7 +118,6 @@ class parser
{
{
json_sax_dom_parser
<
BasicJsonType
>
sdp
(
result
,
allow_exceptions
);
json_sax_dom_parser
<
BasicJsonType
>
sdp
(
result
,
allow_exceptions
);
sax_parse_internal
(
&
sdp
);
sax_parse_internal
(
&
sdp
);
result
.
assert_invariant
();
// in strict mode, input must be completely read
// in strict mode, input must be completely read
if
(
strict
&&
(
get_token
()
!=
token_type
::
end_of_input
))
if
(
strict
&&
(
get_token
()
!=
token_type
::
end_of_input
))
...
@@ -137,6 +135,8 @@ class parser
...
@@ -137,6 +135,8 @@ class parser
return
;
return
;
}
}
}
}
result
.
assert_invariant
();
}
}
/*!
/*!
...
...
include/nlohmann/json.hpp
View file @
ff57bdcc
...
@@ -1233,13 +1233,29 @@ class basic_json
...
@@ -1233,13 +1233,29 @@ class basic_json
invariant. Furthermore, it has to be called each time the type of a JSON
invariant. Furthermore, it has to be called each time the type of a JSON
value is changed, because the invariant expresses a relationship between
value is changed, because the invariant expresses a relationship between
@a m_type and @a m_value.
@a m_type and @a m_value.
Furthermore, the parent relation is checked for arrays and objects: If
@a check_parents true and the value is an array or object, then the
container's elements must have the current value as parent.
@param[in] check_parents whether the parent relation should be checked.
The value is true by default and should only be set to true
during destruction of objects when the invariant does not
need to hold.
*/
*/
void
assert_invariant
()
const
noexcept
void
assert_invariant
(
bool
check_parents
=
true
)
const
noexcept
{
{
JSON_ASSERT
(
m_type
!=
value_t
::
object
||
m_value
.
object
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
object
||
m_value
.
object
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
array
||
m_value
.
array
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
array
||
m_value
.
array
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
string
||
m_value
.
string
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
string
||
m_value
.
string
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
binary
||
m_value
.
binary
!=
nullptr
);
JSON_ASSERT
(
m_type
!=
value_t
::
binary
||
m_value
.
binary
!=
nullptr
);
#if JSON_DIAGNOSTICS
JSON_ASSERT
(
!
check_parents
||
!
is_structured
()
||
std
::
all_of
(
begin
(),
end
(),
[
this
](
const
basic_json
&
j
)
{
return
j
.
m_parent
==
this
;
}));
#endif
}
}
reference
set_parent
(
reference
j
,
bool
recursive
)
reference
set_parent
(
reference
j
,
bool
recursive
)
...
@@ -1497,6 +1513,7 @@ class basic_json
...
@@ -1497,6 +1513,7 @@ class basic_json
std
::
forward
<
CompatibleType
>
(
val
))))
std
::
forward
<
CompatibleType
>
(
val
))))
{
{
JSONSerializer
<
U
>::
to_json
(
*
this
,
std
::
forward
<
CompatibleType
>
(
val
));
JSONSerializer
<
U
>::
to_json
(
*
this
,
std
::
forward
<
CompatibleType
>
(
val
));
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
}
}
...
@@ -1575,6 +1592,7 @@ class basic_json
...
@@ -1575,6 +1592,7 @@ class basic_json
default:
// LCOV_EXCL_LINE
default:
// LCOV_EXCL_LINE
JSON_ASSERT
(
false
);
// LCOV_EXCL_LINE
JSON_ASSERT
(
false
);
// LCOV_EXCL_LINE
}
}
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
}
}
...
@@ -1689,10 +1707,9 @@ class basic_json
...
@@ -1689,10 +1707,9 @@ class basic_json
for
(
auto
&
element_ref
:
init
)
for
(
auto
&
element_ref
:
init
)
{
{
auto
element
=
element_ref
.
moved_or_copied
();
auto
element
=
element_ref
.
moved_or_copied
();
auto
res
=
m_value
.
object
->
emplace
(
m_value
.
object
->
emplace
(
std
::
move
(
*
((
*
element
.
m_value
.
array
)[
0
].
m_value
.
string
)),
std
::
move
(
*
((
*
element
.
m_value
.
array
)[
0
].
m_value
.
string
)),
std
::
move
((
*
element
.
m_value
.
array
)[
1
]));
std
::
move
((
*
element
.
m_value
.
array
)[
1
]));
set_parent
(
res
.
first
->
second
,
false
);
}
}
}
}
else
else
...
@@ -1700,9 +1717,9 @@ class basic_json
...
@@ -1700,9 +1717,9 @@ class basic_json
// the initializer list describes an array -> create array
// the initializer list describes an array -> create array
m_type
=
value_t
::
array
;
m_type
=
value_t
::
array
;
m_value
.
array
=
create
<
array_t
>
(
init
.
begin
(),
init
.
end
());
m_value
.
array
=
create
<
array_t
>
(
init
.
begin
(),
init
.
end
());
set_parent
(
*
this
,
true
);
}
}
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
}
}
...
@@ -2045,7 +2062,6 @@ class basic_json
...
@@ -2045,7 +2062,6 @@ class basic_json
{
{
m_value
.
object
=
create
<
object_t
>
(
first
.
m_it
.
object_iterator
,
m_value
.
object
=
create
<
object_t
>
(
first
.
m_it
.
object_iterator
,
last
.
m_it
.
object_iterator
);
last
.
m_it
.
object_iterator
);
set_parent
(
*
this
,
true
);
break
;
break
;
}
}
...
@@ -2053,7 +2069,6 @@ class basic_json
...
@@ -2053,7 +2069,6 @@ class basic_json
{
{
m_value
.
array
=
create
<
array_t
>
(
first
.
m_it
.
array_iterator
,
m_value
.
array
=
create
<
array_t
>
(
first
.
m_it
.
array_iterator
,
last
.
m_it
.
array_iterator
);
last
.
m_it
.
array_iterator
);
set_parent
(
*
this
,
true
);
break
;
break
;
}
}
...
@@ -2067,6 +2082,7 @@ class basic_json
...
@@ -2067,6 +2082,7 @@ class basic_json
JSON_THROW
(
invalid_iterator
::
create
(
206
,
"cannot construct with iterators from "
+
std
::
string
(
first
.
m_object
->
type_name
()),
diagnostics_t
()));
JSON_THROW
(
invalid_iterator
::
create
(
206
,
"cannot construct with iterators from "
+
std
::
string
(
first
.
m_object
->
type_name
()),
diagnostics_t
()));
}
}
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
}
}
...
@@ -2116,14 +2132,12 @@ class basic_json
...
@@ -2116,14 +2132,12 @@ class basic_json
case
value_t
:
:
object
:
case
value_t
:
:
object
:
{
{
m_value
=
*
other
.
m_value
.
object
;
m_value
=
*
other
.
m_value
.
object
;
set_parent
(
*
this
,
true
);
break
;
break
;
}
}
case
value_t
:
:
array
:
case
value_t
:
:
array
:
{
{
m_value
=
*
other
.
m_value
.
array
;
m_value
=
*
other
.
m_value
.
array
;
set_parent
(
*
this
,
true
);
break
;
break
;
}
}
...
@@ -2167,6 +2181,7 @@ class basic_json
...
@@ -2167,6 +2181,7 @@ class basic_json
break
;
break
;
}
}
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
}
}
...
@@ -2201,7 +2216,7 @@ class basic_json
...
@@ -2201,7 +2216,7 @@ class basic_json
m_value
(
std
::
move
(
other
.
m_value
))
m_value
(
std
::
move
(
other
.
m_value
))
{
{
// check that passed value is valid
// check that passed value is valid
other
.
assert_invariant
();
other
.
assert_invariant
(
false
);
// invalidate payload
// invalidate payload
other
.
m_type
=
value_t
::
null
;
other
.
m_type
=
value_t
::
null
;
...
@@ -2248,6 +2263,7 @@ class basic_json
...
@@ -2248,6 +2263,7 @@ class basic_json
swap
(
m_type
,
other
.
m_type
);
swap
(
m_type
,
other
.
m_type
);
swap
(
m_value
,
other
.
m_value
);
swap
(
m_value
,
other
.
m_value
);
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
return
*
this
;
return
*
this
;
}
}
...
@@ -2269,7 +2285,7 @@ class basic_json
...
@@ -2269,7 +2285,7 @@ class basic_json
*/
*/
~
basic_json
()
noexcept
~
basic_json
()
noexcept
{
{
assert_invariant
();
assert_invariant
(
false
);
m_value
.
destroy
(
m_type
);
m_value
.
destroy
(
m_type
);
}
}
...
@@ -5990,6 +6006,8 @@ class basic_json
...
@@ -5990,6 +6006,8 @@ class basic_json
{
{
std
::
swap
(
m_type
,
other
.
m_type
);
std
::
swap
(
m_type
,
other
.
m_type
);
std
::
swap
(
m_value
,
other
.
m_value
);
std
::
swap
(
m_value
,
other
.
m_value
);
set_parent
(
*
this
,
true
);
assert_invariant
();
assert_invariant
();
}
}
...
...
single_include/nlohmann/json.hpp
View file @
ff57bdcc
This diff is collapsed.
Click to expand it.
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