🚧 better diagnostics

pull/2562/head
Niels Lohmann 2021-01-01 17:23:10 +01:00
parent 68c3696382
commit a4d491e22d
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
2 changed files with 222 additions and 2 deletions

View File

@ -1642,6 +1642,9 @@ class basic_json
std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
{
auto element = element_ref.moved_or_copied();
#ifdef JSON_DIAGNOSTICS
(*element.m_value.array)[1].m_parent = this;
#endif
m_value.object->emplace(
std::move(*((*element.m_value.array)[0].m_value.string)),
std::move((*element.m_value.array)[1]));
@ -1652,6 +1655,12 @@ 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());
#ifdef JSON_DIAGNOSTICS
for (auto& element : *m_value.array)
{
element.m_parent = this;
}
#endif
}
assert_invariant();
@ -2696,6 +2705,49 @@ class basic_json
/// @}
private:
#ifdef JSON_DIAGNOSTICS
std::string diagnostics()
{
std::string result;
for (basic_json* current = this; current->m_parent != nullptr; current = current->m_parent)
{
switch (current->m_parent->type())
{
case value_t::array:
{
for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
{
if (current->m_parent->m_value.array->operator[](i) == *current)
{
result = "/" + std::to_string(i) + result;
continue;
}
}
break;
}
case value_t::object:
{
for (auto it : *current->m_parent->m_value.object)
{
if (it.second == *current)
{
result = "/" + it.first + result;
continue;
}
}
break;
}
default:
break;
}
}
return result;
}
#endif
//////////////////
// value access //
//////////////////
@ -3318,7 +3370,13 @@ class basic_json
{
JSON_TRY
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.array->at(idx);
result.m_parent = this;
return result;
#else
return m_value.array->at(idx);
#endif
}
JSON_CATCH (std::out_of_range&)
{
@ -3416,7 +3474,13 @@ class basic_json
{
JSON_TRY
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.object->at(key);
result.m_parent = this;
return result;
#else
return m_value.object->at(key);
#endif
}
JSON_CATCH (std::out_of_range&)
{
@ -3525,9 +3589,18 @@ class basic_json
m_value.array->insert(m_value.array->end(),
idx - m_value.array->size() + 1,
basic_json());
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
}
#ifdef JSON_DIAGNOSTICS
reference result = m_value.array->operator[](idx);
result.m_parent = this;
return result;
#else
return m_value.array->operator[](idx);
#endif
}
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
@ -3603,7 +3676,13 @@ class basic_json
// operator[] only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.object->operator[](key);
result.m_parent = this;
return result;
#else
return m_value.object->operator[](key);
#endif
}
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
@ -3693,7 +3772,13 @@ class basic_json
// at only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.object->operator[](key);
result.m_parent = this;
return result;
#else
return m_value.object->operator[](key);
#endif
}
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
@ -5249,6 +5334,9 @@ class basic_json
// add element to array (move semantics)
m_value.array->push_back(std::move(val));
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
}
@ -5284,6 +5372,9 @@ class basic_json
// add element to array
m_value.array->push_back(val);
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
}
/*!
@ -5332,8 +5423,13 @@ class basic_json
assert_invariant();
}
// add element to array
// add element to object
#ifdef JSON_DIAGNOSTICS
auto res = m_value.object->insert(val);
res.first->second.m_parent = this;
#else
m_value.object->insert(val);
#endif
}
/*!
@ -5437,9 +5533,18 @@ class basic_json
// add element to array (perfect forwarding)
#ifdef JSON_HAS_CPP_17
#ifdef JSON_DIAGNOSTICS
reference result = m_value.array->emplace_back(std::forward<Args>(args)...);
result.m_parent = this;
return result;
#else
return m_value.array->emplace_back(std::forward<Args>(args)...);
#endif
#else
m_value.array->emplace_back(std::forward<Args>(args)...);
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
return m_value.array->back();
#endif
}
@ -6967,6 +7072,11 @@ class basic_json
/// the value of the current element
json_value m_value = {};
#ifdef JSON_DIAGNOSTICS
/// a pointer to a parent value (for debugging purposes)
basic_json* m_parent = nullptr;
#endif
//////////////////////////////////////////
// binary serialization/deserialization //
//////////////////////////////////////////

View File

@ -18266,6 +18266,9 @@ class basic_json
std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
{
auto element = element_ref.moved_or_copied();
#ifdef JSON_DIAGNOSTICS
(*element.m_value.array)[1].m_parent = this;
#endif
m_value.object->emplace(
std::move(*((*element.m_value.array)[0].m_value.string)),
std::move((*element.m_value.array)[1]));
@ -18276,6 +18279,12 @@ 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());
#ifdef JSON_DIAGNOSTICS
for (auto& element : *m_value.array)
{
element.m_parent = this;
}
#endif
}
assert_invariant();
@ -19320,6 +19329,49 @@ class basic_json
/// @}
private:
#ifdef JSON_DIAGNOSTICS
std::string diagnostics()
{
std::string result;
for (basic_json* current = this; current->m_parent != nullptr; current = current->m_parent)
{
switch (current->m_parent->type())
{
case value_t::array:
{
for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
{
if (current->m_parent->m_value.array->operator[](i) == *current)
{
result = "/" + std::to_string(i) + result;
continue;
}
}
break;
}
case value_t::object:
{
for (auto it : *current->m_parent->m_value.object)
{
if (it.second == *current)
{
result = "/" + it.first + result;
continue;
}
}
break;
}
default:
break;
}
}
return result;
}
#endif
//////////////////
// value access //
//////////////////
@ -19942,7 +19994,13 @@ class basic_json
{
JSON_TRY
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.array->at(idx);
result.m_parent = this;
return result;
#else
return m_value.array->at(idx);
#endif
}
JSON_CATCH (std::out_of_range&)
{
@ -20040,7 +20098,13 @@ class basic_json
{
JSON_TRY
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.object->at(key);
result.m_parent = this;
return result;
#else
return m_value.object->at(key);
#endif
}
JSON_CATCH (std::out_of_range&)
{
@ -20149,9 +20213,18 @@ class basic_json
m_value.array->insert(m_value.array->end(),
idx - m_value.array->size() + 1,
basic_json());
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
}
#ifdef JSON_DIAGNOSTICS
reference result = m_value.array->operator[](idx);
result.m_parent = this;
return result;
#else
return m_value.array->operator[](idx);
#endif
}
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
@ -20227,7 +20300,13 @@ class basic_json
// operator[] only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.object->operator[](key);
result.m_parent = this;
return result;
#else
return m_value.object->operator[](key);
#endif
}
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
@ -20317,7 +20396,13 @@ class basic_json
// at only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
#ifdef JSON_DIAGNOSTICS
reference result = m_value.object->operator[](key);
result.m_parent = this;
return result;
#else
return m_value.object->operator[](key);
#endif
}
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
@ -21873,6 +21958,9 @@ class basic_json
// add element to array (move semantics)
m_value.array->push_back(std::move(val));
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
}
@ -21908,6 +21996,9 @@ class basic_json
// add element to array
m_value.array->push_back(val);
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
}
/*!
@ -21956,8 +22047,13 @@ class basic_json
assert_invariant();
}
// add element to array
// add element to object
#ifdef JSON_DIAGNOSTICS
auto res = m_value.object->insert(val);
res.first->second.m_parent = this;
#else
m_value.object->insert(val);
#endif
}
/*!
@ -22061,9 +22157,18 @@ class basic_json
// add element to array (perfect forwarding)
#ifdef JSON_HAS_CPP_17
#ifdef JSON_DIAGNOSTICS
reference result = m_value.array->emplace_back(std::forward<Args>(args)...);
result.m_parent = this;
return result;
#else
return m_value.array->emplace_back(std::forward<Args>(args)...);
#endif
#else
m_value.array->emplace_back(std::forward<Args>(args)...);
#ifdef JSON_DIAGNOSTICS
m_value.array->back().m_parent = this;
#endif
return m_value.array->back();
#endif
}
@ -23591,6 +23696,11 @@ class basic_json
/// the value of the current element
json_value m_value = {};
#ifdef JSON_DIAGNOSTICS
/// a pointer to a parent value (for debugging purposes)
basic_json* m_parent = nullptr;
#endif
//////////////////////////////////////////
// binary serialization/deserialization //
//////////////////////////////////////////