mirror of
https://github.com/nlohmann/json.git
synced 2025-08-07 18:02:57 +03:00
@@ -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, "type must be null, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
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, "type must be number, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, "type must be boolean, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
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, "type must be string, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
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, "type must be string, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
|
||||
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, "type must be array, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
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, "type must be array, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
l.resize(j.size());
|
||||
std::transform(j.begin(), j.end(), std::begin(l),
|
||||
@@ -241,8 +241,7 @@ void())
|
||||
{
|
||||
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, "type must be array, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
|
||||
from_json_array_impl(j, arr, priority_tag<3> {});
|
||||
@@ -253,7 +252,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, "type must be binary, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
|
||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||
@@ -265,7 +264,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, "type must be object, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
|
||||
ConstructibleObjectType ret;
|
||||
@@ -319,7 +318,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, "type must be number, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,14 +347,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, "type must be array, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
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, "type must be array, but is " + std::string(p.type_name()), j));
|
||||
}
|
||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||
}
|
||||
@@ -368,14 +367,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, "type must be array, but is " + std::string(j.type_name()), j));
|
||||
}
|
||||
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, "type must be array, but is " + std::string(p.type_name()), j));
|
||||
}
|
||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||
}
|
||||
|
@@ -132,6 +132,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = arr;
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@@ -140,6 +141,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = std::move(arr);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@@ -152,6 +154,7 @@ struct external_constructor<value_t::array>
|
||||
using std::end;
|
||||
j.m_type = value_t::array;
|
||||
j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@@ -164,6 +167,7 @@ struct external_constructor<value_t::array>
|
||||
for (const bool x : arr)
|
||||
{
|
||||
j.m_value.array->push_back(x);
|
||||
j.set_parent(j.m_value.array->back());
|
||||
}
|
||||
j.assert_invariant();
|
||||
}
|
||||
@@ -179,6 +183,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
|
||||
}
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@@ -191,6 +196,7 @@ struct external_constructor<value_t::object>
|
||||
{
|
||||
j.m_type = value_t::object;
|
||||
j.m_value = obj;
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@@ -199,6 +205,7 @@ struct external_constructor<value_t::object>
|
||||
{
|
||||
j.m_type = value_t::object;
|
||||
j.m_value = std::move(obj);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@@ -211,6 +218,7 @@ struct external_constructor<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.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
|
@@ -4,6 +4,8 @@
|
||||
#include <stdexcept> // runtime_error
|
||||
#include <string> // to_string
|
||||
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
#include <nlohmann/detail/string_escape.hpp>
|
||||
#include <nlohmann/detail/input/position_t.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
@@ -65,6 +67,61 @@ class exception : public std::exception
|
||||
return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
static std::string diagnostics(const BasicJsonType& leaf_element)
|
||||
{
|
||||
#if JSON_DIAGNOSTICS
|
||||
std::vector<std::string> tokens;
|
||||
for (const auto* current = &leaf_element; 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 (¤t->m_parent->m_value.array->operator[](i) == current)
|
||||
{
|
||||
tokens.emplace_back(std::to_string(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
for (const auto& element : *current->m_parent->m_value.object)
|
||||
{
|
||||
if (&element.second == current)
|
||||
{
|
||||
tokens.emplace_back(element.first.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
break; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
|
||||
[](const std::string & a, const std::string & b)
|
||||
{
|
||||
return a + "/" + detail::escape(b);
|
||||
}) + ") ";
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
/// an exception object as storage for error messages
|
||||
std::runtime_error m;
|
||||
@@ -127,18 +184,20 @@ class parse_error : public exception
|
||||
@param[in] what_arg the explanatory string
|
||||
@return parse_error object
|
||||
*/
|
||||
static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
|
||||
template<typename BasicJsonType>
|
||||
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
|
||||
{
|
||||
std::string w = exception::name("parse_error", id_) + "parse error" +
|
||||
position_string(pos) + ": " + what_arg;
|
||||
position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
|
||||
return parse_error(id_, pos.chars_read_total, w.c_str());
|
||||
}
|
||||
|
||||
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
|
||||
template<typename BasicJsonType>
|
||||
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
|
||||
{
|
||||
std::string w = exception::name("parse_error", id_) + "parse error" +
|
||||
(byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
|
||||
": " + what_arg;
|
||||
": " + exception::diagnostics(context) + what_arg;
|
||||
return parse_error(id_, byte_, w.c_str());
|
||||
}
|
||||
|
||||
@@ -204,9 +263,10 @@ caught.,invalid_iterator}
|
||||
class invalid_iterator : public exception
|
||||
{
|
||||
public:
|
||||
static invalid_iterator create(int id_, const std::string& what_arg)
|
||||
template<typename BasicJsonType>
|
||||
static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
|
||||
{
|
||||
std::string w = exception::name("invalid_iterator", id_) + what_arg;
|
||||
std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
|
||||
return invalid_iterator(id_, w.c_str());
|
||||
}
|
||||
|
||||
@@ -258,9 +318,10 @@ caught.,type_error}
|
||||
class type_error : public exception
|
||||
{
|
||||
public:
|
||||
static type_error create(int id_, const std::string& what_arg)
|
||||
template<typename BasicJsonType>
|
||||
static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
|
||||
{
|
||||
std::string w = exception::name("type_error", id_) + what_arg;
|
||||
std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
|
||||
return type_error(id_, w.c_str());
|
||||
}
|
||||
|
||||
@@ -305,9 +366,10 @@ caught.,out_of_range}
|
||||
class out_of_range : public exception
|
||||
{
|
||||
public:
|
||||
static out_of_range create(int id_, const std::string& what_arg)
|
||||
template<typename BasicJsonType>
|
||||
static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
|
||||
{
|
||||
std::string w = exception::name("out_of_range", id_) + what_arg;
|
||||
std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
|
||||
return out_of_range(id_, w.c_str());
|
||||
}
|
||||
|
||||
@@ -343,9 +405,10 @@ caught.,other_error}
|
||||
class other_error : public exception
|
||||
{
|
||||
public:
|
||||
static other_error create(int id_, const std::string& what_arg)
|
||||
template<typename BasicJsonType>
|
||||
static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
|
||||
{
|
||||
std::string w = exception::name("other_error", id_) + what_arg;
|
||||
std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
|
||||
return other_error(id_, w.c_str());
|
||||
}
|
||||
|
||||
|
@@ -137,7 +137,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(),
|
||||
parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
|
||||
parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
|
||||
}
|
||||
|
||||
return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
|
||||
@@ -234,7 +234,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
|
||||
}
|
||||
|
||||
// All BSON binary values have a subtype
|
||||
@@ -316,7 +316,7 @@ class binary_reader
|
||||
{
|
||||
std::array<char, 3> cr{{}};
|
||||
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
|
||||
return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
|
||||
return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,7 +716,7 @@ class binary_reader
|
||||
case cbor_tag_handler_t::error:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
|
||||
}
|
||||
|
||||
case cbor_tag_handler_t::ignore:
|
||||
@@ -831,7 +831,7 @@ class binary_reader
|
||||
default: // anything else (0xFF is handled inside the other types)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -926,7 +926,7 @@ class binary_reader
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1025,7 +1025,7 @@ class binary_reader
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1492,7 +1492,7 @@ class binary_reader
|
||||
default: // anything else
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1574,7 +1574,7 @@ class binary_reader
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1824,7 +1824,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1894,7 +1894,7 @@ class binary_reader
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1932,7 +1932,7 @@ class binary_reader
|
||||
return false;
|
||||
}
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
|
||||
}
|
||||
|
||||
return get_ubjson_size_value(result.first);
|
||||
@@ -2022,7 +2022,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
|
||||
}
|
||||
string_t s(1, static_cast<typename string_t::value_type>(current));
|
||||
return sax->string(s);
|
||||
@@ -2043,7 +2043,7 @@ class binary_reader
|
||||
default: // anything else
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2221,7 +2221,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
|
||||
{
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number")));
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
|
||||
}
|
||||
|
||||
switch (result_number)
|
||||
@@ -2233,7 +2233,7 @@ class binary_reader
|
||||
case token_type::value_float:
|
||||
return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
|
||||
default:
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number")));
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2389,7 +2389,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
|
||||
{
|
||||
return sax->parse_error(chars_read, "<end of file>",
|
||||
parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
|
||||
parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -219,8 +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,
|
||||
"excessive object size: " + std::to_string(len)));
|
||||
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -235,6 +234,7 @@ class json_sax_dom_parser
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
ref_stack.back()->set_parents();
|
||||
ref_stack.pop_back();
|
||||
return true;
|
||||
}
|
||||
@@ -245,8 +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,
|
||||
"excessive array size: " + std::to_string(len)));
|
||||
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -254,6 +253,7 @@ class json_sax_dom_parser
|
||||
|
||||
bool end_array()
|
||||
{
|
||||
ref_stack.back()->set_parents();
|
||||
ref_stack.pop_back();
|
||||
return true;
|
||||
}
|
||||
@@ -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, "excessive object size: " + std::to_string(len), *ref_stack.back()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -425,10 +425,17 @@ class json_sax_dom_callback_parser
|
||||
|
||||
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
|
||||
*ref_stack.back() = discarded;
|
||||
if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
|
||||
{
|
||||
// discard object
|
||||
*ref_stack.back() = discarded;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref_stack.back()->set_parents();
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
@@ -463,7 +470,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, "excessive array size: " + std::to_string(len), *ref_stack.back()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -476,7 +483,11 @@ class json_sax_dom_callback_parser
|
||||
if (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_parents();
|
||||
}
|
||||
else
|
||||
{
|
||||
// discard array
|
||||
*ref_stack.back() = discarded;
|
||||
@@ -574,7 +585,7 @@ class json_sax_dom_callback_parser
|
||||
// array
|
||||
if (ref_stack.back()->is_array())
|
||||
{
|
||||
ref_stack.back()->m_value.array->push_back(std::move(value));
|
||||
ref_stack.back()->m_value.array->emplace_back(std::move(value));
|
||||
return {true, &(ref_stack.back()->m_value.array->back())};
|
||||
}
|
||||
|
||||
|
@@ -88,7 +88,6 @@ class parser
|
||||
{
|
||||
json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
|
||||
sax_parse_internal(&sdp);
|
||||
result.assert_invariant();
|
||||
|
||||
// in strict mode, input must be completely read
|
||||
if (strict && (get_token() != token_type::end_of_input))
|
||||
@@ -96,7 +95,7 @@ class parser
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_of_input, "value")));
|
||||
exception_message(token_type::end_of_input, "value"), BasicJsonType()));
|
||||
}
|
||||
|
||||
// in case of an error, return discarded value
|
||||
@@ -117,15 +116,13 @@ class parser
|
||||
{
|
||||
json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
|
||||
sax_parse_internal(&sdp);
|
||||
result.assert_invariant();
|
||||
|
||||
// in strict mode, input must be completely read
|
||||
if (strict && (get_token() != token_type::end_of_input))
|
||||
{
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_of_input, "value")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
|
||||
}
|
||||
|
||||
// in case of an error, return discarded value
|
||||
@@ -135,6 +132,8 @@ class parser
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
result.assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -161,8 +160,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_of_input, "value")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -208,8 +206,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::value_string, "object key")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||
{
|
||||
@@ -221,8 +218,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::name_separator, "object separator")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
|
||||
}
|
||||
|
||||
// remember we are now inside an object
|
||||
@@ -265,7 +261,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
|
||||
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
|
||||
@@ -335,16 +331,14 @@ class parser
|
||||
// using "uninitialized" to avoid "expected" message
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::uninitialized, "value")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
|
||||
}
|
||||
|
||||
default: // the last token was unexpected
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::literal_or_value, "value")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -390,8 +384,7 @@ class parser
|
||||
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_array, "array")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
|
||||
}
|
||||
|
||||
// states.back() is false -> object
|
||||
@@ -404,8 +397,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::value_string, "object key")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||
@@ -418,8 +410,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::name_separator, "object separator")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
|
||||
}
|
||||
|
||||
// parse values
|
||||
@@ -447,8 +438,7 @@ class parser
|
||||
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_object, "object")));
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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, "cannot get value", *m_object));
|
||||
|
||||
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, "cannot get value", *m_object));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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, "cannot get value", *m_object));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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, "cannot compare iterators of different containers", *m_object));
|
||||
}
|
||||
|
||||
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, "cannot compare iterators of different containers", *m_object));
|
||||
}
|
||||
|
||||
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, "cannot compare order of object iterators", *m_object));
|
||||
|
||||
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, "cannot use offsets with object iterators", *m_object));
|
||||
|
||||
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, "cannot use offsets with object iterators", *m_object));
|
||||
|
||||
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, "cannot use operator[] for object iterators", *m_object));
|
||||
|
||||
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, "cannot get value", *m_object));
|
||||
|
||||
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, "cannot get value", *m_object));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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, "cannot use key() for non-object iterators", *m_object));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/string_escape.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
@@ -67,7 +68,7 @@ class json_pointer
|
||||
std::string{},
|
||||
[](const std::string & a, const std::string & b)
|
||||
{
|
||||
return a + "/" + escape(b);
|
||||
return a + "/" + detail::escape(b);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -247,7 +248,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
|
||||
}
|
||||
|
||||
reference_tokens.pop_back();
|
||||
@@ -271,7 +272,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
|
||||
}
|
||||
|
||||
return reference_tokens.back();
|
||||
@@ -337,15 +338,13 @@ class json_pointer
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(106, 0,
|
||||
"array index '" + s +
|
||||
"' must not begin with '0'"));
|
||||
JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
|
||||
}
|
||||
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
|
||||
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
|
||||
}
|
||||
|
||||
std::size_t processed_chars = 0;
|
||||
@@ -356,20 +355,20 @@ class json_pointer
|
||||
}
|
||||
JSON_CATCH(std::out_of_range&)
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
|
||||
}
|
||||
|
||||
// check if the string was completely read
|
||||
if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
|
||||
}
|
||||
|
||||
// only triggered on special platforms (like 32bit), see also
|
||||
// https://github.com/nlohmann/json/pull/2203
|
||||
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
|
||||
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return static_cast<size_type>(res);
|
||||
@@ -380,7 +379,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
|
||||
}
|
||||
|
||||
json_pointer result = *this;
|
||||
@@ -443,7 +442,7 @@ class json_pointer
|
||||
single value; that is, with an empty list of reference tokens.
|
||||
*/
|
||||
default:
|
||||
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
|
||||
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,7 +514,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +547,7 @@ class json_pointer
|
||||
// "-" always fails the range check
|
||||
JSON_THROW(detail::out_of_range::create(402,
|
||||
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
|
||||
") is out of range"));
|
||||
") is out of range", *ptr));
|
||||
}
|
||||
|
||||
// note: at performs range check
|
||||
@@ -557,7 +556,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,9 +594,7 @@ class json_pointer
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
||||
{
|
||||
// "-" cannot be used for const access
|
||||
JSON_THROW(detail::out_of_range::create(402,
|
||||
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
|
||||
") is out of range"));
|
||||
JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
|
||||
}
|
||||
|
||||
// use unchecked array access
|
||||
@@ -606,7 +603,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,7 +636,7 @@ class json_pointer
|
||||
// "-" always fails the range check
|
||||
JSON_THROW(detail::out_of_range::create(402,
|
||||
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
|
||||
") is out of range"));
|
||||
") is out of range", *ptr));
|
||||
}
|
||||
|
||||
// note: at performs range check
|
||||
@@ -648,7 +645,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -752,9 +749,7 @@ class json_pointer
|
||||
// check if nonempty reference string begins with slash
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(107, 1,
|
||||
"JSON pointer must be empty or begin with '/' - was: '" +
|
||||
reference_string + "'"));
|
||||
JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
|
||||
}
|
||||
|
||||
// extract the reference tokens:
|
||||
@@ -789,58 +784,18 @@ class json_pointer
|
||||
(reference_token[pos + 1] != '0' &&
|
||||
reference_token[pos + 1] != '1')))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
|
||||
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
|
||||
}
|
||||
}
|
||||
|
||||
// finally, store the reference token
|
||||
unescape(reference_token);
|
||||
detail::unescape(reference_token);
|
||||
result.push_back(reference_token);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief replace all occurrences of a substring by another string
|
||||
|
||||
@param[in,out] s the string to manipulate; changed so that all
|
||||
occurrences of @a f are replaced with @a t
|
||||
@param[in] f the substring to replace with @a t
|
||||
@param[in] t the string to replace @a f
|
||||
|
||||
@pre The search string @a f must not be empty. **This precondition is
|
||||
enforced with an assertion.**
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
static void replace_substring(std::string& s, const std::string& f,
|
||||
const std::string& t)
|
||||
{
|
||||
JSON_ASSERT(!f.empty());
|
||||
for (auto pos = s.find(f); // find first occurrence of f
|
||||
pos != std::string::npos; // make sure f was found
|
||||
s.replace(pos, f.size(), t), // replace with t, and
|
||||
pos = s.find(f, pos + t.size())) // find next occurrence of f
|
||||
{}
|
||||
}
|
||||
|
||||
JSON_PRIVATE_UNLESS_TESTED:
|
||||
/// escape "~" to "~0" and "/" to "~1"
|
||||
static std::string escape(std::string s)
|
||||
{
|
||||
replace_substring(s, "~", "~0");
|
||||
replace_substring(s, "/", "~1");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// unescape "~1" to tilde and "~0" to slash (order is important!)
|
||||
static void unescape(std::string& s)
|
||||
{
|
||||
replace_substring(s, "~1", "/");
|
||||
replace_substring(s, "~0", "~");
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
@param[in] reference_string the reference string to the current value
|
||||
@@ -886,7 +841,7 @@ class json_pointer
|
||||
// iterate object and use keys as reference string
|
||||
for (const auto& element : *value.m_value.object)
|
||||
{
|
||||
flatten(reference_string + "/" + escape(element.first), element.second, result);
|
||||
flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -916,7 +871,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
|
||||
{
|
||||
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
|
||||
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
|
||||
}
|
||||
|
||||
BasicJsonType result;
|
||||
@@ -926,7 +881,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
|
||||
{
|
||||
JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
|
||||
JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
|
||||
}
|
||||
|
||||
// assign value to reference pointed to by JSON pointer; Note that if
|
||||
|
@@ -57,7 +57,7 @@ class binary_writer
|
||||
|
||||
default:
|
||||
{
|
||||
JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
|
||||
JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -901,13 +901,12 @@ class binary_writer
|
||||
@return The size of a BSON document entry header, including the id marker
|
||||
and the entry name size (and its null-terminator).
|
||||
*/
|
||||
static std::size_t calc_bson_entry_header_size(const string_t& name)
|
||||
static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
|
||||
{
|
||||
const auto it = name.find(static_cast<typename string_t::value_type>(0));
|
||||
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(409,
|
||||
"BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
|
||||
JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
|
||||
}
|
||||
|
||||
return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
|
||||
@@ -1017,21 +1016,21 @@ class binary_writer
|
||||
@brief Writes a BSON element with key @a name and unsigned @a value
|
||||
*/
|
||||
void write_bson_unsigned(const string_t& name,
|
||||
const std::uint64_t value)
|
||||
const BasicJsonType& j)
|
||||
{
|
||||
if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
|
||||
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
|
||||
{
|
||||
write_bson_entry_header(name, 0x10 /* int32 */);
|
||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
|
||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
|
||||
else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
|
||||
{
|
||||
write_bson_entry_header(name, 0x12 /* int64 */);
|
||||
write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
|
||||
write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
|
||||
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1108,7 +1107,7 @@ class binary_writer
|
||||
static std::size_t calc_bson_element_size(const string_t& name,
|
||||
const BasicJsonType& j)
|
||||
{
|
||||
const auto header_size = calc_bson_entry_header_size(name);
|
||||
const auto header_size = calc_bson_entry_header_size(name, j);
|
||||
switch (j.type())
|
||||
{
|
||||
case value_t::object:
|
||||
@@ -1177,7 +1176,7 @@ class binary_writer
|
||||
return write_bson_integer(name, j.m_value.number_integer);
|
||||
|
||||
case value_t::number_unsigned:
|
||||
return write_bson_unsigned(name, j.m_value.number_unsigned);
|
||||
return write_bson_unsigned(name, j);
|
||||
|
||||
case value_t::string:
|
||||
return write_bson_string(name, *j.m_value.string);
|
||||
|
@@ -499,7 +499,7 @@ class serializer
|
||||
{
|
||||
std::string sn(3, '\0');
|
||||
(std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
|
||||
JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
|
||||
JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn, BasicJsonType()));
|
||||
}
|
||||
|
||||
case error_handler_t::ignore:
|
||||
@@ -593,7 +593,7 @@ class serializer
|
||||
{
|
||||
std::string sn(3, '\0');
|
||||
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
|
||||
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
|
||||
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn, BasicJsonType()));
|
||||
}
|
||||
|
||||
case error_handler_t::ignore:
|
||||
|
63
include/nlohmann/detail/string_escape.hpp
Normal file
63
include/nlohmann/detail/string_escape.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/*!
|
||||
@brief replace all occurrences of a substring by another string
|
||||
|
||||
@param[in,out] s the string to manipulate; changed so that all
|
||||
occurrences of @a f are replaced with @a t
|
||||
@param[in] f the substring to replace with @a t
|
||||
@param[in] t the string to replace @a f
|
||||
|
||||
@pre The search string @a f must not be empty. **This precondition is
|
||||
enforced with an assertion.**
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
inline void replace_substring(std::string& s, const std::string& f,
|
||||
const std::string& t)
|
||||
{
|
||||
JSON_ASSERT(!f.empty());
|
||||
for (auto pos = s.find(f); // find first occurrence of f
|
||||
pos != std::string::npos; // make sure f was found
|
||||
s.replace(pos, f.size(), t), // replace with t, and
|
||||
pos = s.find(f, pos + t.size())) // find next occurrence of f
|
||||
{}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief string escaping as described in RFC 6901 (Sect. 4)
|
||||
* @param[in] s string to escape
|
||||
* @return escaped string
|
||||
*
|
||||
* Note the order of escaping "~" to "~0" and "/" to "~1" is important.
|
||||
*/
|
||||
inline std::string escape(std::string s)
|
||||
{
|
||||
replace_substring(s, "~", "~0");
|
||||
replace_substring(s, "/", "~1");
|
||||
return s;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief string unescaping as described in RFC 6901 (Sect. 4)
|
||||
* @param[in] s string to unescape
|
||||
* @return unescaped string
|
||||
*
|
||||
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
|
||||
*/
|
||||
static void unescape(std::string& s)
|
||||
{
|
||||
replace_substring(s, "~1", "/");
|
||||
replace_substring(s, "~0", "~");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
@@ -32,7 +32,7 @@ number_float), because the library distinguishes these three types for numbers:
|
||||
@ref basic_json::number_float_t is used for floating-point numbers or to
|
||||
approximate integers which do not fit in the limits of their respective type.
|
||||
|
||||
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
|
||||
@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
|
||||
value with the default value for a given type
|
||||
|
||||
@since version 1.0.0
|
||||
|
@@ -189,6 +189,7 @@ class basic_json
|
||||
friend class ::nlohmann::detail::json_sax_dom_parser;
|
||||
template<typename BasicJsonType>
|
||||
friend class ::nlohmann::detail::json_sax_dom_callback_parser;
|
||||
friend class ::nlohmann::detail::exception;
|
||||
|
||||
/// workaround type for MSVC
|
||||
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
|
||||
@@ -1060,7 +1061,7 @@ class basic_json
|
||||
object = nullptr; // silence warning, see #821
|
||||
if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
|
||||
{
|
||||
JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE
|
||||
JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1", basic_json())); // LCOV_EXCL_LINE
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1227,13 +1228,83 @@ 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 false
|
||||
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;
|
||||
}));
|
||||
#else
|
||||
static_cast<void>(check_parents);
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_parents()
|
||||
{
|
||||
#if JSON_DIAGNOSTICS
|
||||
switch (m_type)
|
||||
{
|
||||
case value_t::array:
|
||||
{
|
||||
for (auto& element : *m_value.array)
|
||||
{
|
||||
element.m_parent = this;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
for (auto& element : *m_value.object)
|
||||
{
|
||||
element.second.m_parent = this;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
iterator set_parents(iterator it, typename iterator::difference_type count)
|
||||
{
|
||||
#if JSON_DIAGNOSTICS
|
||||
for (typename iterator::difference_type i = 0; i < count; ++i)
|
||||
{
|
||||
(it + i)->m_parent = this;
|
||||
}
|
||||
#else
|
||||
static_cast<void>(count);
|
||||
#endif
|
||||
return it;
|
||||
}
|
||||
|
||||
reference set_parent(reference j)
|
||||
{
|
||||
#if JSON_DIAGNOSTICS
|
||||
j.m_parent = this;
|
||||
#else
|
||||
static_cast<void>(j);
|
||||
#endif
|
||||
return j;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1450,6 +1521,7 @@ class basic_json
|
||||
std::forward<CompatibleType>(val))))
|
||||
{
|
||||
JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -1528,6 +1600,7 @@ class basic_json
|
||||
default: // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -1629,7 +1702,7 @@ class basic_json
|
||||
// if object is wanted but impossible, throw an exception
|
||||
if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
|
||||
{
|
||||
JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
|
||||
JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1639,13 +1712,13 @@ class basic_json
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
|
||||
std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
|
||||
for (auto& element_ref : init)
|
||||
{
|
||||
auto element = element_ref.moved_or_copied();
|
||||
m_value.object->emplace(
|
||||
std::move(*((*element.m_value.array)[0].m_value.string)),
|
||||
std::move((*element.m_value.array)[1]));
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1654,6 +1727,7 @@ class basic_json
|
||||
m_value.array = create<array_t>(init.begin(), init.end());
|
||||
}
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -1863,6 +1937,7 @@ class basic_json
|
||||
: m_type(value_t::array)
|
||||
{
|
||||
m_value.array = create<array_t>(cnt, val);
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -1932,7 +2007,7 @@ class basic_json
|
||||
// make sure iterator fits the current value
|
||||
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
|
||||
JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
|
||||
}
|
||||
|
||||
// copy type from first iterator
|
||||
@@ -1950,7 +2025,7 @@ class basic_json
|
||||
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|
||||
|| !last.m_it.primitive_iterator.is_end()))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
|
||||
JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2012,10 +2087,10 @@ class basic_json
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
|
||||
std::string(first.m_object->type_name())));
|
||||
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
|
||||
}
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -2114,6 +2189,7 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -2148,12 +2224,13 @@ 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;
|
||||
other.m_value = {};
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -2194,6 +2271,7 @@ class basic_json
|
||||
swap(m_type, other.m_type);
|
||||
swap(m_value, other.m_value);
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
return *this;
|
||||
}
|
||||
@@ -2215,7 +2293,7 @@ class basic_json
|
||||
*/
|
||||
~basic_json() noexcept
|
||||
{
|
||||
assert_invariant();
|
||||
assert_invariant(false);
|
||||
m_value.destroy(m_type);
|
||||
}
|
||||
|
||||
@@ -2708,7 +2786,7 @@ class basic_json
|
||||
return m_value.boolean;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/// get a pointer to the value (object)
|
||||
@@ -2829,7 +2907,7 @@ class basic_json
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
|
||||
JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -3257,7 +3335,7 @@ class basic_json
|
||||
{
|
||||
if (!is_binary())
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
return *get_ptr<binary_t*>();
|
||||
@@ -3268,7 +3346,7 @@ class basic_json
|
||||
{
|
||||
if (!is_binary())
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
return *get_ptr<const binary_t*>();
|
||||
@@ -3318,17 +3396,17 @@ class basic_json
|
||||
{
|
||||
JSON_TRY
|
||||
{
|
||||
return m_value.array->at(idx);
|
||||
return set_parent(m_value.array->at(idx));
|
||||
}
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3370,12 +3448,12 @@ class basic_json
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3416,17 +3494,17 @@ class basic_json
|
||||
{
|
||||
JSON_TRY
|
||||
{
|
||||
return m_value.object->at(key);
|
||||
return set_parent(m_value.object->at(key));
|
||||
}
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
|
||||
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3472,12 +3550,12 @@ class basic_json
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
|
||||
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3522,15 +3600,22 @@ class basic_json
|
||||
// fill up array with null values if given idx is outside range
|
||||
if (idx >= m_value.array->size())
|
||||
{
|
||||
m_value.array->insert(m_value.array->end(),
|
||||
idx - m_value.array->size() + 1,
|
||||
basic_json());
|
||||
#if JSON_DIAGNOSTICS
|
||||
// remember array size before resizing
|
||||
const auto previous_size = m_value.array->size();
|
||||
#endif
|
||||
m_value.array->resize(idx + 1);
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
// set parent for values added above
|
||||
set_parents(begin() + static_cast<typename iterator::difference_type>(previous_size), static_cast<typename iterator::difference_type>(idx + 1 - previous_size));
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_value.array->operator[](idx);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3560,7 +3645,7 @@ class basic_json
|
||||
return m_value.array->operator[](idx);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3603,10 +3688,10 @@ class basic_json
|
||||
// operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return m_value.object->operator[](key);
|
||||
return set_parent(m_value.object->operator[](key));
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3648,7 +3733,7 @@ class basic_json
|
||||
return m_value.object->find(key)->second;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3693,10 +3778,10 @@ class basic_json
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return m_value.object->operator[](key);
|
||||
return set_parent(m_value.object->operator[](key));
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3740,7 +3825,7 @@ class basic_json
|
||||
return m_value.object->find(key)->second;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3812,7 +3897,7 @@ class basic_json
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3885,7 +3970,7 @@ class basic_json
|
||||
}
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -4039,7 +4124,7 @@ class basic_json
|
||||
// make sure iterator fits the current value
|
||||
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
|
||||
}
|
||||
|
||||
IteratorType result = end();
|
||||
@@ -4055,7 +4140,7 @@ class basic_json
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
|
||||
JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
|
||||
}
|
||||
|
||||
if (is_string())
|
||||
@@ -4091,7 +4176,7 @@ class basic_json
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -4152,7 +4237,7 @@ class basic_json
|
||||
// make sure iterator fits the current value
|
||||
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
|
||||
JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
|
||||
}
|
||||
|
||||
IteratorType result = end();
|
||||
@@ -4169,7 +4254,7 @@ class basic_json
|
||||
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
|
||||
|| !last.m_it.primitive_iterator.is_end()))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
|
||||
JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
|
||||
}
|
||||
|
||||
if (is_string())
|
||||
@@ -4207,7 +4292,7 @@ class basic_json
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -4250,7 +4335,7 @@ class basic_json
|
||||
return m_value.object->erase(key);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -4284,14 +4369,14 @@ class basic_json
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(idx >= size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
|
||||
}
|
||||
|
||||
m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5236,7 +5321,7 @@ class basic_json
|
||||
// push_back only works for null objects or arrays
|
||||
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
|
||||
{
|
||||
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// transform null object into an array
|
||||
@@ -5249,6 +5334,7 @@ class basic_json
|
||||
|
||||
// add element to array (move semantics)
|
||||
m_value.array->push_back(std::move(val));
|
||||
set_parent(m_value.array->back());
|
||||
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
|
||||
}
|
||||
|
||||
@@ -5271,7 +5357,7 @@ class basic_json
|
||||
// push_back only works for null objects or arrays
|
||||
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
|
||||
{
|
||||
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// transform null object into an array
|
||||
@@ -5284,6 +5370,7 @@ class basic_json
|
||||
|
||||
// add element to array
|
||||
m_value.array->push_back(val);
|
||||
set_parent(m_value.array->back());
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5321,7 +5408,7 @@ class basic_json
|
||||
// push_back only works for null objects or objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
|
||||
{
|
||||
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// transform null object into an object
|
||||
@@ -5332,8 +5419,9 @@ class basic_json
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
// add element to array
|
||||
m_value.object->insert(val);
|
||||
// add element to object
|
||||
auto res = m_value.object->insert(val);
|
||||
set_parent(res.first->second);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5424,7 +5512,7 @@ class basic_json
|
||||
// emplace_back only works for null objects or arrays
|
||||
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
|
||||
{
|
||||
JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// transform null object into an array
|
||||
@@ -5437,10 +5525,10 @@ class basic_json
|
||||
|
||||
// add element to array (perfect forwarding)
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
return m_value.array->emplace_back(std::forward<Args>(args)...);
|
||||
return set_parent(m_value.array->emplace_back(std::forward<Args>(args)...));
|
||||
#else
|
||||
m_value.array->emplace_back(std::forward<Args>(args)...);
|
||||
return m_value.array->back();
|
||||
return set_parent(m_value.array->back());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5477,7 +5565,7 @@ class basic_json
|
||||
// emplace only works for null objects or arrays
|
||||
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
|
||||
{
|
||||
JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// transform null object into an object
|
||||
@@ -5490,6 +5578,8 @@ class basic_json
|
||||
|
||||
// add element to array (perfect forwarding)
|
||||
auto res = m_value.object->emplace(std::forward<Args>(args)...);
|
||||
set_parent(res.first->second);
|
||||
|
||||
// create result iterator and set iterator to the result of emplace
|
||||
auto it = begin();
|
||||
it.m_it.object_iterator = res.first;
|
||||
@@ -5548,14 +5638,14 @@ class basic_json
|
||||
// check if iterator pos fits to this JSON value
|
||||
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
|
||||
}
|
||||
|
||||
// insert to array and return iterator
|
||||
return insert_iterator(pos, val);
|
||||
return set_parents(insert_iterator(pos, val), static_cast<typename iterator::difference_type>(1));
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5599,14 +5689,14 @@ class basic_json
|
||||
// check if iterator pos fits to this JSON value
|
||||
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
|
||||
}
|
||||
|
||||
// insert to array and return iterator
|
||||
return insert_iterator(pos, cnt, val);
|
||||
return set_parents(insert_iterator(pos, cnt, val), static_cast<typename iterator::difference_type>(cnt));
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5644,28 +5734,28 @@ class basic_json
|
||||
// insert only works for arrays
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// check if iterator pos fits to this JSON value
|
||||
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
|
||||
}
|
||||
|
||||
// check if range iterators belong to the same JSON object
|
||||
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
|
||||
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
|
||||
JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
|
||||
}
|
||||
|
||||
// insert to array and return iterator
|
||||
return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
|
||||
return set_parents(insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator), std::distance(first, last));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5697,17 +5787,17 @@ class basic_json
|
||||
// insert only works for arrays
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// check if iterator pos fits to this JSON value
|
||||
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
|
||||
}
|
||||
|
||||
// insert to array and return iterator
|
||||
return insert_iterator(pos, ilist.begin(), ilist.end());
|
||||
return set_parents(insert_iterator(pos, ilist.begin(), ilist.end()), static_cast<typename iterator::difference_type>(ilist.size()));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5738,19 +5828,19 @@ class basic_json
|
||||
// insert only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// check if range iterators belong to the same JSON object
|
||||
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
|
||||
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
|
||||
}
|
||||
|
||||
// passed iterators must belong to objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
|
||||
}
|
||||
|
||||
m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
|
||||
@@ -5787,11 +5877,11 @@ class basic_json
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
|
||||
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), *this));
|
||||
}
|
||||
|
||||
for (auto it = j.cbegin(); it != j.cend(); ++it)
|
||||
@@ -5838,20 +5928,20 @@ class basic_json
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
|
||||
}
|
||||
|
||||
// check if range iterators belong to the same JSON object
|
||||
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
|
||||
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
|
||||
}
|
||||
|
||||
// passed iterators must belong to objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()
|
||||
|| !last.m_object->is_object()))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
|
||||
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
|
||||
}
|
||||
|
||||
for (auto it = first; it != last; ++it)
|
||||
@@ -5886,6 +5976,9 @@ class basic_json
|
||||
{
|
||||
std::swap(m_type, other.m_type);
|
||||
std::swap(m_value, other.m_value);
|
||||
|
||||
set_parents();
|
||||
other.set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@@ -5946,7 +6039,7 @@ class basic_json
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5979,7 +6072,7 @@ class basic_json
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6012,7 +6105,7 @@ class basic_json
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6045,7 +6138,7 @@ class basic_json
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6059,7 +6152,7 @@ class basic_json
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6967,6 +7060,11 @@ class basic_json
|
||||
/// the value of the current element
|
||||
json_value m_value = {};
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
/// a pointer to a parent value (for debugging purposes)
|
||||
basic_json* m_parent = nullptr;
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////
|
||||
// binary serialization/deserialization //
|
||||
//////////////////////////////////////////
|
||||
@@ -8263,7 +8361,7 @@ class basic_json
|
||||
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
|
||||
{
|
||||
// avoid undefined behavior
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
|
||||
}
|
||||
|
||||
// default case: insert add offset
|
||||
@@ -8279,7 +8377,7 @@ class basic_json
|
||||
};
|
||||
|
||||
// wrapper for "remove" operation; remove value at ptr
|
||||
const auto operation_remove = [&result](json_pointer & ptr)
|
||||
const auto operation_remove = [this, &result](json_pointer & ptr)
|
||||
{
|
||||
// get reference to parent of JSON pointer ptr
|
||||
const auto last_path = ptr.back();
|
||||
@@ -8297,7 +8395,7 @@ class basic_json
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
|
||||
JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
|
||||
}
|
||||
}
|
||||
else if (parent.is_array())
|
||||
@@ -8310,7 +8408,7 @@ class basic_json
|
||||
// type check: top level value must be an array
|
||||
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
|
||||
{
|
||||
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
|
||||
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
|
||||
}
|
||||
|
||||
// iterate and apply the operations
|
||||
@@ -8330,13 +8428,13 @@ class basic_json
|
||||
// check if desired value is present
|
||||
if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
|
||||
{
|
||||
JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
|
||||
JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
|
||||
}
|
||||
|
||||
// check if result is of type string
|
||||
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
|
||||
{
|
||||
JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
|
||||
JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
|
||||
}
|
||||
|
||||
// no error: return value
|
||||
@@ -8346,7 +8444,7 @@ class basic_json
|
||||
// type check: every element of the array must be an object
|
||||
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
|
||||
{
|
||||
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
|
||||
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
|
||||
}
|
||||
|
||||
// collect mandatory members
|
||||
@@ -8424,7 +8522,7 @@ class basic_json
|
||||
// throw an exception if test fails
|
||||
if (JSON_HEDLEY_UNLIKELY(!success))
|
||||
{
|
||||
JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
|
||||
JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -8434,7 +8532,7 @@ class basic_json
|
||||
{
|
||||
// op must be "add", "remove", "replace", "move", "copy", or
|
||||
// "test"
|
||||
JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
|
||||
JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8550,7 +8648,7 @@ class basic_json
|
||||
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
||||
{
|
||||
// escape the key name to be used in a JSON patch
|
||||
const auto key = json_pointer::escape(it.key());
|
||||
const auto key = detail::escape(it.key());
|
||||
|
||||
if (target.find(it.key()) != target.end())
|
||||
{
|
||||
@@ -8574,7 +8672,7 @@ class basic_json
|
||||
if (source.find(it.key()) == source.end())
|
||||
{
|
||||
// found a key that is not in this -> add it
|
||||
const auto key = json_pointer::escape(it.key());
|
||||
const auto key = detail::escape(it.key());
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "add"}, {"path", path + "/" + key},
|
||||
|
Reference in New Issue
Block a user