mirror of
https://github.com/nlohmann/json.git
synced 2025-07-24 02:21:01 +03:00
🐛 fix invariants
This commit is contained in:
@ -1233,13 +1233,29 @@ class basic_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
|
||||
@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::array || m_value.array != nullptr);
|
||||
JSON_ASSERT(m_type != value_t::string || m_value.string != 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)
|
||||
@ -1497,6 +1513,7 @@ class basic_json
|
||||
std::forward<CompatibleType>(val))))
|
||||
{
|
||||
JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -1575,6 +1592,7 @@ class basic_json
|
||||
default: // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -1689,10 +1707,9 @@ class basic_json
|
||||
for (auto& element_ref : init)
|
||||
{
|
||||
auto element = element_ref.moved_or_copied();
|
||||
auto res = m_value.object->emplace(
|
||||
std::move(*((*element.m_value.array)[0].m_value.string)),
|
||||
std::move((*element.m_value.array)[1]));
|
||||
set_parent(res.first->second, false);
|
||||
m_value.object->emplace(
|
||||
std::move(*((*element.m_value.array)[0].m_value.string)),
|
||||
std::move((*element.m_value.array)[1]));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1700,9 +1717,9 @@ class basic_json
|
||||
// the initializer list describes an array -> create array
|
||||
m_type = value_t::array;
|
||||
m_value.array = create<array_t>(init.begin(), init.end());
|
||||
set_parent(*this, true);
|
||||
}
|
||||
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -2045,7 +2062,6 @@ class basic_json
|
||||
{
|
||||
m_value.object = create<object_t>(first.m_it.object_iterator,
|
||||
last.m_it.object_iterator);
|
||||
set_parent(*this, true);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2053,7 +2069,6 @@ class basic_json
|
||||
{
|
||||
m_value.array = create<array_t>(first.m_it.array_iterator,
|
||||
last.m_it.array_iterator);
|
||||
set_parent(*this, true);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -2116,14 +2132,12 @@ class basic_json
|
||||
case value_t::object:
|
||||
{
|
||||
m_value = *other.m_value.object;
|
||||
set_parent(*this, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
m_value = *other.m_value.array;
|
||||
set_parent(*this, true);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2167,6 +2181,7 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -2201,7 +2216,7 @@ class basic_json
|
||||
m_value(std::move(other.m_value))
|
||||
{
|
||||
// check that passed value is valid
|
||||
other.assert_invariant();
|
||||
other.assert_invariant(false);
|
||||
|
||||
// invalidate payload
|
||||
other.m_type = value_t::null;
|
||||
@ -2248,6 +2263,7 @@ class basic_json
|
||||
swap(m_type, other.m_type);
|
||||
swap(m_value, other.m_value);
|
||||
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
return *this;
|
||||
}
|
||||
@ -2269,7 +2285,7 @@ class basic_json
|
||||
*/
|
||||
~basic_json() noexcept
|
||||
{
|
||||
assert_invariant();
|
||||
assert_invariant(false);
|
||||
m_value.destroy(m_type);
|
||||
}
|
||||
|
||||
@ -5990,6 +6006,8 @@ class basic_json
|
||||
{
|
||||
std::swap(m_type, other.m_type);
|
||||
std::swap(m_value, other.m_value);
|
||||
|
||||
set_parent(*this, true);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user