🚧 add diagnostics to exceptions

parent a4d491e2
...@@ -27,7 +27,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n) ...@@ -27,7 +27,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_null())) if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
{ {
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be null, but is " + std::string(j.type_name())));
} }
n = nullptr; n = nullptr;
} }
...@@ -58,7 +58,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) ...@@ -58,7 +58,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
} }
default: default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be number, but is " + std::string(j.type_name())));
} }
} }
...@@ -67,7 +67,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) ...@@ -67,7 +67,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
{ {
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be boolean, but is " + std::string(j.type_name())));
} }
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
} }
...@@ -77,7 +77,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) ...@@ -77,7 +77,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_string())) if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{ {
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be string, but is " + std::string(j.type_name())));
} }
s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
} }
...@@ -93,7 +93,7 @@ void from_json(const BasicJsonType& j, ConstructibleStringType& s) ...@@ -93,7 +93,7 @@ void from_json(const BasicJsonType& j, ConstructibleStringType& s)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_string())) if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{ {
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be string, but is " + std::string(j.type_name())));
} }
s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
...@@ -133,7 +133,7 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) ...@@ -133,7 +133,7 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_array())) if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
} }
l.clear(); l.clear();
std::transform(j.rbegin(), j.rend(), std::transform(j.rbegin(), j.rend(),
...@@ -150,7 +150,7 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l) ...@@ -150,7 +150,7 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_array())) if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
} }
l.resize(j.size()); l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l), std::transform(j.begin(), j.end(), std::begin(l),
...@@ -241,7 +241,7 @@ void()) ...@@ -241,7 +241,7 @@ void())
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_array())) if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " +
std::string(j.type_name()))); std::string(j.type_name())));
} }
...@@ -253,7 +253,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) ...@@ -253,7 +253,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
{ {
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be binary, but is " + std::string(j.type_name())));
} }
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
...@@ -265,7 +265,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) ...@@ -265,7 +265,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_object())) if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{ {
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be object, but is " + std::string(j.type_name())));
} }
ConstructibleObjectType ret; ConstructibleObjectType ret;
...@@ -319,7 +319,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) ...@@ -319,7 +319,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
} }
default: default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be number, but is " + std::string(j.type_name())));
} }
} }
...@@ -348,14 +348,14 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& ...@@ -348,14 +348,14 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_array())) if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
} }
m.clear(); m.clear();
for (const auto& p : j) for (const auto& p : j)
{ {
if (JSON_HEDLEY_UNLIKELY(!p.is_array())) if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(p.type_name())));
} }
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
} }
...@@ -368,14 +368,14 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE ...@@ -368,14 +368,14 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_array())) if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
} }
m.clear(); m.clear();
for (const auto& p : j) for (const auto& p : j)
{ {
if (JSON_HEDLEY_UNLIKELY(!p.is_array())) if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(p.type_name())));
} }
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
} }
......
...@@ -219,7 +219,7 @@ class json_sax_dom_parser ...@@ -219,7 +219,7 @@ class json_sax_dom_parser
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() +
"excessive object size: " + std::to_string(len))); "excessive object size: " + std::to_string(len)));
} }
...@@ -245,7 +245,7 @@ class json_sax_dom_parser ...@@ -245,7 +245,7 @@ class json_sax_dom_parser
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() +
"excessive array size: " + std::to_string(len))); "excessive array size: " + std::to_string(len)));
} }
...@@ -400,7 +400,7 @@ class json_sax_dom_callback_parser ...@@ -400,7 +400,7 @@ class json_sax_dom_callback_parser
// check object limit // check object limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() + "excessive object size: " + std::to_string(len)));
} }
return true; return true;
...@@ -463,7 +463,7 @@ class json_sax_dom_callback_parser ...@@ -463,7 +463,7 @@ class json_sax_dom_callback_parser
// check array limit // check array limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{ {
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() + "excessive array size: " + std::to_string(len)));
} }
return true; return true;
......
...@@ -257,7 +257,7 @@ class iter_impl ...@@ -257,7 +257,7 @@ class iter_impl
} }
case value_t::null: case value_t::null:
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
default: default:
{ {
...@@ -266,7 +266,7 @@ class iter_impl ...@@ -266,7 +266,7 @@ class iter_impl
return *m_object; return *m_object;
} }
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
} }
} }
} }
...@@ -300,7 +300,7 @@ class iter_impl ...@@ -300,7 +300,7 @@ class iter_impl
return m_object; return m_object;
} }
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
} }
} }
} }
...@@ -401,7 +401,7 @@ class iter_impl ...@@ -401,7 +401,7 @@ class iter_impl
// if objects are not the same, the comparison is undefined // if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{ {
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); JSON_THROW(invalid_iterator::create(212, m_object->diagnostics() + "cannot compare iterators of different containers"));
} }
JSON_ASSERT(m_object != nullptr); JSON_ASSERT(m_object != nullptr);
...@@ -438,7 +438,7 @@ class iter_impl ...@@ -438,7 +438,7 @@ class iter_impl
// if objects are not the same, the comparison is undefined // if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{ {
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); JSON_THROW(invalid_iterator::create(212, m_object->diagnostics() + "cannot compare iterators of different containers"));
} }
JSON_ASSERT(m_object != nullptr); JSON_ASSERT(m_object != nullptr);
...@@ -446,7 +446,7 @@ class iter_impl ...@@ -446,7 +446,7 @@ class iter_impl
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); JSON_THROW(invalid_iterator::create(213, m_object->diagnostics() + "cannot compare order of object iterators"));
case value_t::array: case value_t::array:
return (m_it.array_iterator < other.m_it.array_iterator); return (m_it.array_iterator < other.m_it.array_iterator);
...@@ -494,7 +494,7 @@ class iter_impl ...@@ -494,7 +494,7 @@ class iter_impl
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); JSON_THROW(invalid_iterator::create(209, m_object->diagnostics() + "cannot use offsets with object iterators"));
case value_t::array: case value_t::array:
{ {
...@@ -565,7 +565,7 @@ class iter_impl ...@@ -565,7 +565,7 @@ class iter_impl
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); JSON_THROW(invalid_iterator::create(209, m_object->diagnostics() + "cannot use offsets with object iterators"));
case value_t::array: case value_t::array:
return m_it.array_iterator - other.m_it.array_iterator; return m_it.array_iterator - other.m_it.array_iterator;
...@@ -586,13 +586,13 @@ class iter_impl ...@@ -586,13 +586,13 @@ class iter_impl
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); JSON_THROW(invalid_iterator::create(208, m_object->diagnostics() + "cannot use operator[] for object iterators"));
case value_t::array: case value_t::array:
return *std::next(m_it.array_iterator, n); return *std::next(m_it.array_iterator, n);
case value_t::null: case value_t::null:
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
default: default:
{ {
...@@ -601,7 +601,7 @@ class iter_impl ...@@ -601,7 +601,7 @@ class iter_impl
return *m_object; return *m_object;
} }
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
} }
} }
} }
...@@ -619,7 +619,7 @@ class iter_impl ...@@ -619,7 +619,7 @@ class iter_impl
return m_it.object_iterator->first; return m_it.object_iterator->first;
} }
JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); JSON_THROW(invalid_iterator::create(207, m_object->diagnostics() + "cannot use key() for non-object iterators"));
} }
/*! /*!
......
...@@ -2155,6 +2155,9 @@ class basic_json ...@@ -2155,6 +2155,9 @@ class basic_json
basic_json(basic_json&& other) noexcept basic_json(basic_json&& other) noexcept
: m_type(std::move(other.m_type)), : m_type(std::move(other.m_type)),
m_value(std::move(other.m_value)) m_value(std::move(other.m_value))
#ifdef JSON_DIAGNOSTICS
, m_parent(other.m_parent)
#endif
{ {
// check that passed value is valid // check that passed value is valid
other.assert_invariant(); other.assert_invariant();
...@@ -2704,12 +2707,11 @@ class basic_json ...@@ -2704,12 +2707,11 @@ class basic_json
/// @} /// @}
private: std::string diagnostics() const
#ifdef JSON_DIAGNOSTICS
std::string diagnostics()
{ {
std::string result; #ifdef JSON_DIAGNOSTICS
for (basic_json* current = this; current->m_parent != nullptr; current = current->m_parent) std::vector<std::string> tokens;
for (const basic_json* current = this; current->m_parent != nullptr; current = current->m_parent)
{ {
switch (current->m_parent->type()) switch (current->m_parent->type())
{ {
...@@ -2719,7 +2721,7 @@ class basic_json ...@@ -2719,7 +2721,7 @@ class basic_json
{ {
if (current->m_parent->m_value.array->operator[](i) == *current) if (current->m_parent->m_value.array->operator[](i) == *current)
{ {
result = "/" + std::to_string(i) + result; tokens.emplace_back(std::to_string(i));
continue; continue;
} }
} }
...@@ -2728,11 +2730,11 @@ class basic_json ...@@ -2728,11 +2730,11 @@ class basic_json
case value_t::object: case value_t::object:
{ {
for (auto it : *current->m_parent->m_value.object) for (const auto& element : *current->m_parent->m_value.object)
{ {
if (it.second == *current) if (element.second == *current)
{ {
result = "/" + it.first + result; tokens.emplace_back(element.first.c_str());
continue; continue;
} }
} }
...@@ -2744,10 +2746,22 @@ class basic_json ...@@ -2744,10 +2746,22 @@ class basic_json
} }
} }
return result; if (tokens.empty())
} {
return "";
}
return "(" + std::accumulate(tokens.begin(), tokens.end(), std::string{},
[](const std::string & a, const std::string & b)
{
return a + "/" + b;
}) + ") ";
#else
return "";
#endif #endif
}
private:
////////////////// //////////////////
// value access // // value access //
////////////////// //////////////////
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment