🚧 add diagnostics to exceptions

parent a4d491e2
......@@ -27,7 +27,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
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;
}
......@@ -58,7 +58,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
}
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)
{
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*>();
}
......@@ -77,7 +77,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
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*>();
}
......@@ -93,7 +93,7 @@ void from_json(const BasicJsonType& j, ConstructibleStringType& s)
{
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*>();
......@@ -133,7 +133,7 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
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();
std::transform(j.rbegin(), j.rend(),
......@@ -150,7 +150,7 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
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());
std::transform(j.begin(), j.end(), std::begin(l),
......@@ -241,7 +241,7 @@ void())
{
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())));
}
......@@ -253,7 +253,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{
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*>();
......@@ -265,7 +265,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
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;
......@@ -319,7 +319,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
}
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>&
{
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();
for (const auto& p : j)
{
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>());
}
......@@ -368,14 +368,14 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
{
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();
for (const auto& p : j)
{
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>());
}
......
......@@ -219,7 +219,7 @@ class json_sax_dom_parser
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)));
}
......@@ -245,7 +245,7 @@ class json_sax_dom_parser
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)));
}
......@@ -400,7 +400,7 @@ class json_sax_dom_callback_parser
// check object limit
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;
......@@ -463,7 +463,7 @@ class json_sax_dom_callback_parser
// check array limit
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;
......
......@@ -257,7 +257,7 @@ class iter_impl
}
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:
{
......@@ -266,7 +266,7 @@ class iter_impl
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
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
// if objects are not the same, the comparison is undefined
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);
......@@ -438,7 +438,7 @@ class iter_impl
// if objects are not the same, the comparison is undefined
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);
......@@ -446,7 +446,7 @@ class iter_impl
switch (m_object->m_type)
{
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:
return (m_it.array_iterator < other.m_it.array_iterator);
......@@ -494,7 +494,7 @@ class iter_impl
switch (m_object->m_type)
{
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:
{
......@@ -565,7 +565,7 @@ class iter_impl
switch (m_object->m_type)
{
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:
return m_it.array_iterator - other.m_it.array_iterator;
......@@ -586,13 +586,13 @@ class iter_impl
switch (m_object->m_type)
{
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:
return *std::next(m_it.array_iterator, n);
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:
{
......@@ -601,7 +601,7 @@ class iter_impl
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
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
basic_json(basic_json&& other) noexcept
: m_type(std::move(other.m_type)),
m_value(std::move(other.m_value))
#ifdef JSON_DIAGNOSTICS
, m_parent(other.m_parent)
#endif
{
// check that passed value is valid
other.assert_invariant();
......@@ -2704,12 +2707,11 @@ class basic_json
/// @}
private:
#ifdef JSON_DIAGNOSTICS
std::string diagnostics()
std::string diagnostics() const
{
std::string result;
for (basic_json* current = this; current->m_parent != nullptr; current = current->m_parent)
#ifdef JSON_DIAGNOSTICS
std::vector<std::string> tokens;
for (const basic_json* current = this; current->m_parent != nullptr; current = current->m_parent)
{
switch (current->m_parent->type())
{
......@@ -2719,7 +2721,7 @@ class basic_json
{
if (current->m_parent->m_value.array->operator[](i) == *current)
{
result = "/" + std::to_string(i) + result;
tokens.emplace_back(std::to_string(i));
continue;
}
}
......@@ -2728,11 +2730,11 @@ class basic_json
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;
}
}
......@@ -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
}
private:
//////////////////
// 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