Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bb0e4166b | ||
|
|
673c470c66 |
No files matched your search
@@ -463,6 +463,65 @@ JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_literal(const exceptio
|
|||||||
JSON_THROW(ExceptionType::create(id_, what_arg, context));
|
JSON_THROW(ExceptionType::create(id_, what_arg, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSON Patch errors; constructed out of line so that patch_inplace() does not carry them
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_add_parent(const BasicJsonType& parent)
|
||||||
|
{
|
||||||
|
static_cast<void>(parent);
|
||||||
|
JSON_THROW(out_of_range::create(exception_id::patch_add_parent_not_container, concat("cannot add value: the JSON Patch 'add' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_remove_parent(const BasicJsonType& parent)
|
||||||
|
{
|
||||||
|
static_cast<void>(parent);
|
||||||
|
JSON_THROW(out_of_range::create(exception_id::patch_remove_parent_not_container, concat("cannot remove value: the JSON Patch 'remove' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_not_an_array(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
static_cast<void>(j);
|
||||||
|
JSON_THROW(parse_error::create(exception_id::patch_not_an_array, 0, "JSON patch must be an array of objects", &j));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_missing_member(const StringType& op, const StringType& member, const bool string_type, const BasicJsonType& val)
|
||||||
|
{
|
||||||
|
static_cast<void>(op);
|
||||||
|
static_cast<void>(member);
|
||||||
|
static_cast<void>(string_type);
|
||||||
|
static_cast<void>(val);
|
||||||
|
// context-sensitive error message
|
||||||
|
const std::string error_msg = (op == "op") ? std::string("operation") : concat("operation '", op, '\'');
|
||||||
|
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat(error_msg, string_type ? " must have string member '" : " must have member '", member, "'"), &val));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_move_into_child(const StringType& from_path, const StringType& path, const BasicJsonType& result)
|
||||||
|
{
|
||||||
|
static_cast<void>(from_path);
|
||||||
|
static_cast<void>(path);
|
||||||
|
static_cast<void>(result);
|
||||||
|
JSON_THROW(out_of_range::create(exception_id::patch_move_into_child, concat("cannot move value: 'from' path '", from_path, "' is a proper prefix of 'path' '", path, "'"), &result));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_test_failed(const BasicJsonType& val)
|
||||||
|
{
|
||||||
|
static_cast<void>(val);
|
||||||
|
JSON_THROW(other_error::create(exception_id::patch_test_failed, concat("unsuccessful: ", val.dump()), &val));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_invalid_operation(const StringType& op, const BasicJsonType& val)
|
||||||
|
{
|
||||||
|
static_cast<void>(op);
|
||||||
|
static_cast<void>(val);
|
||||||
|
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat("operation value '", op, "' is invalid"), &val));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ class binary_reader
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_end_of_input, concat("expected end of input; last byte: 0x", get_token_string()), "value");
|
return last_byte_error(exception_id::unexpected_end_of_input, "expected end of input", "value", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document");
|
return bson_document_size_error(document_size, chars_read - document_start);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -509,7 +509,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("string length must be at least 1, is ", std::to_string(len)), "string");
|
return bson_length_error("string length must be at least 1, is ", len, "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
||||||
@@ -539,7 +539,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary");
|
return bson_length_error("byte array length cannot be negative, is ", len, "binary");
|
||||||
}
|
}
|
||||||
|
|
||||||
// All BSON binary values have a subtype
|
// All BSON binary values have a subtype
|
||||||
@@ -629,9 +629,7 @@ class binary_reader
|
|||||||
|
|
||||||
default: // anything else is not supported (yet)
|
default: // anything else is not supported (yet)
|
||||||
{
|
{
|
||||||
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
return bson_unsupported_type_error(element_type_parse_position, element_type);
|
||||||
return sax->parse_error(element_type_parse_position, cr_str,
|
|
||||||
parse_error::create(exception_id::bson_unsupported_type, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1060,6 +1058,7 @@ class binary_reader
|
|||||||
@param[in] context parsing context for the error message
|
@param[in] context parsing context for the error message
|
||||||
@return whether the SAX consumer accepts the parse error
|
@return whether the SAX consumer accepts the parse error
|
||||||
*/
|
*/
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("indefinite-length ", type_name, " is not allowed inside indefinite-length ", type_name, "; last byte: 0x", get_token_string()), context);
|
return last_byte_error(exception_id::invalid_string_or_size, concat("indefinite-length ", type_name, " is not allowed inside indefinite-length ", type_name, "; last byte: 0x", get_token_string()), context);
|
||||||
@@ -1139,7 +1138,7 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0x60-0x7B)", inside_indefinite ? "" : " or indefinite string type (0x7F)", "; last byte: 0x", get_token_string()), "string");
|
return last_byte_error(exception_id::invalid_string_or_size, "expected length specification (0x60-0x7B)", "string", inside_indefinite ? "" : " or indefinite string type (0x7F)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1269,7 +1268,7 @@ class binary_reader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("only string keys are supported, but found ", found, "; last byte: 0x", get_token_string()), "object key");
|
return last_byte_error(exception_id::invalid_string_or_size, "only string keys are supported, but found ", "object key", found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1350,7 +1349,7 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0x40-0x5B)", inside_indefinite ? "" : " or indefinite binary array type (0x5F)", "; last byte: 0x", get_token_string()), "binary");
|
return last_byte_error(exception_id::invalid_string_or_size, "expected length specification (0x40-0x5B)", "binary", inside_indefinite ? "" : " or indefinite binary array type (0x5F)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1496,8 +1495,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return container_size_error(context);
|
||||||
exception_message(concat("excessive ", context, " size"), "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
result = conditional_static_cast<std::size_t>(len);
|
result = conditional_static_cast<std::size_t>(len);
|
||||||
return true;
|
return true;
|
||||||
@@ -2065,7 +2063,7 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", get_token_string()), "string");
|
return last_byte_error(exception_id::invalid_string_or_size, "expected length specification (0xA0-0xBF, 0xD9-0xDB)", "string", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2157,7 +2155,7 @@ class binary_reader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("only string keys are supported, but found ", found, "; last byte: 0x", get_token_string()), "object key");
|
return last_byte_error(exception_id::invalid_string_or_size, "only string keys are supported, but found ", "object key", found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -2655,8 +2653,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return out_of_range_error(exception_id::container_too_large, "integer value overflow", "size");
|
||||||
exception_message("integer value overflow", "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
|
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
|
||||||
return true;
|
return true;
|
||||||
@@ -2753,8 +2750,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (!value_in_range_of<std::size_t>(number))
|
if (!value_in_range_of<std::size_t>(number))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return out_of_range_error(exception_id::container_too_large, "integer value overflow", "size");
|
||||||
exception_message("integer value overflow", "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
result = detail::conditional_static_cast<std::size_t>(number);
|
result = detail::conditional_static_cast<std::size_t>(number);
|
||||||
return true;
|
return true;
|
||||||
@@ -2832,7 +2828,7 @@ class binary_reader
|
|||||||
// or SIZE_MAX.
|
// or SIZE_MAX.
|
||||||
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
return out_of_range_error(exception_id::container_too_large, "excessive ndarray size caused overflow", "size");
|
||||||
}
|
}
|
||||||
result *= i;
|
result *= i;
|
||||||
// the pre-check above already rules out result becoming 0
|
// the pre-check above already rules out result becoming 0
|
||||||
@@ -2841,7 +2837,7 @@ class binary_reader
|
|||||||
// unknown-size container (see get_ubjson_size_type())
|
// unknown-size container (see get_ubjson_size_type())
|
||||||
if (result == npos)
|
if (result == npos)
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
return out_of_range_error(exception_id::container_too_large, "excessive ndarray size caused overflow", "size");
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
||||||
{
|
{
|
||||||
@@ -2891,7 +2887,7 @@ class binary_reader
|
|||||||
if (input_format == input_format_t::bjdata
|
if (input_format == input_format_t::bjdata
|
||||||
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
return optimized_type_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
||||||
@@ -2906,7 +2902,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("expected '#' after type information; last byte: 0x", get_token_string()), "size");
|
return last_byte_error(exception_id::unexpected_byte, "expected '#' after type information", "size", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
||||||
@@ -3057,7 +3053,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", get_token_string()), "char");
|
return last_byte_error(exception_id::invalid_string_or_size, "byte after 'C' must be in range 0x00..0x7F", "char", "");
|
||||||
}
|
}
|
||||||
string_t s(1, static_cast<typename string_t::value_type>(current));
|
string_t s(1, static_cast<typename string_t::value_type>(current));
|
||||||
return sax->string(s);
|
return sax->string(s);
|
||||||
@@ -3141,8 +3137,7 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY((size_and_type.second == 'Z' || size_and_type.second == 'T' || size_and_type.second == 'F')
|
if (JSON_HEDLEY_UNLIKELY((size_and_type.second == 'Z' || size_and_type.second == 'T' || size_and_type.second == 'F')
|
||||||
&& size_and_type.first > max_valueless_container_size))
|
&& size_and_type.first > max_valueless_container_size))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return out_of_range_error(exception_id::container_too_large, "excessive array size", "size");
|
||||||
exception_message("excessive array size", "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!enter_array(size_and_type.first, size_and_type.second)))
|
if (JSON_HEDLEY_UNLIKELY(!enter_array(size_and_type.first, size_and_type.second)))
|
||||||
@@ -3854,7 +3849,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
// in case of failure, advance position by 1 to report the failing location
|
// in case of failure, advance position by 1 to report the failing location
|
||||||
++chars_read;
|
++chars_read;
|
||||||
sax->parse_error(chars_read, "<end of file>", parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
static_cast<void>(report_eof(context));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -4007,8 +4002,7 @@ class binary_reader
|
|||||||
const auto result = static_cast<number_float_t>(number);
|
const auto result = static_cast<number_float_t>(number);
|
||||||
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(),
|
return out_of_range_error(exception_id::number_overflow, "number overflow", "value");
|
||||||
out_of_range::create(exception_id::number_overflow, exception_message("number overflow", "value"), nullptr));
|
|
||||||
}
|
}
|
||||||
return sax->number_float(result, "");
|
return sax->number_float(result, "");
|
||||||
}
|
}
|
||||||
@@ -4223,22 +4217,82 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, "<end of file>",
|
return report_eof(context);
|
||||||
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief reports an unexpected end of input (out of line to keep the exception
|
||||||
|
construction out of the hot reading functions)
|
||||||
|
@param[in] context further context information (for diagnostics)
|
||||||
|
@return the result of the SAX parser's parse_error()
|
||||||
|
*/
|
||||||
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool report_eof(const char* context) const
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, "<end of file>",
|
||||||
|
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief reports an out_of_range error at the last read byte (out of line)
|
||||||
|
*/
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool out_of_range_error(const exception_id id_, const char* detail, const char* context) const
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(id_, exception_message(detail, context), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool container_size_error(const char* what) const
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||||
|
exception_message(concat("excessive ", what, " size"), "size"), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool optimized_type_error() const
|
||||||
|
{
|
||||||
|
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool bson_length_error(const char* prefix, const NumberType len, const char* context) const
|
||||||
|
{
|
||||||
|
return last_byte_error(exception_id::unexpected_byte, concat(prefix, std::to_string(len)), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool bson_document_size_error(const std::int32_t document_size, const std::size_t bytes_read) const
|
||||||
|
{
|
||||||
|
return last_byte_error(exception_id::unexpected_byte, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(bytes_read), ")"), "document");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool bson_unsupported_type_error(const std::size_t position, const char element_type) const
|
||||||
|
{
|
||||||
|
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
||||||
|
return sax->parse_error(position, cr_str,
|
||||||
|
parse_error::create(exception_id::bson_unsupported_type, position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief reports a parse error at the last read byte
|
@brief reports a parse error at the last read byte
|
||||||
@param[in] id_ the id of the parse_error exception
|
@param[in] id_ the id of the parse_error exception
|
||||||
@param[in] detail a detailed error message
|
@param[in] detail a detailed error message
|
||||||
@param[in] context further context information
|
@param[in] context further context information
|
||||||
|
@param[in] tail optional text appended to the detail, followed by "; last byte: 0x<token>"
|
||||||
@return the result of the SAX parser's parse_error()
|
@return the result of the SAX parser's parse_error()
|
||||||
*/
|
*/
|
||||||
bool last_byte_error(const exception_id id_, const std::string& detail, const std::string& context) const
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool last_byte_error(const exception_id id_, const std::string& detail, const char* context, const char* tail = nullptr) const
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), parse_error::create(id_, chars_read, exception_message(detail, context), nullptr));
|
// with a tail, the message reads "<detail><tail>; last byte: 0x<token>"
|
||||||
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(id_, chars_read,
|
||||||
|
exception_message(tail == nullptr ? detail : concat(detail, tail, "; last byte: 0x", get_token_string()), context), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -4247,7 +4301,8 @@ class binary_reader
|
|||||||
@param[in] context further context information
|
@param[in] context further context information
|
||||||
@return the result of the SAX parser's parse_error()
|
@return the result of the SAX parser's parse_error()
|
||||||
*/
|
*/
|
||||||
bool unexpected_byte(const char* detail, const std::string& context) const
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool unexpected_byte(const char* detail, const char* context) const
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat(detail, ": 0x", get_token_string()), context);
|
return last_byte_error(exception_id::unexpected_byte, concat(detail, ": 0x", get_token_string()), context);
|
||||||
}
|
}
|
||||||
@@ -4258,6 +4313,7 @@ class binary_reader
|
|||||||
@param[in] context further context information
|
@param[in] context further context information
|
||||||
@return the result of the SAX parser's parse_error()
|
@return the result of the SAX parser's parse_error()
|
||||||
*/
|
*/
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
bool length_type_error(const char* position, const char* context) const
|
bool length_type_error(const char* position, const char* context) const
|
||||||
{
|
{
|
||||||
const char* types = input_format == input_format_t::bjdata ? "U, i, u, I, m, l, M, L" : "U, i, I, l, L";
|
const char* types = input_format == input_format_t::bjdata ? "U, i, u, I, m, l, M, L" : "U, i, I, l, L";
|
||||||
|
|||||||
@@ -187,12 +187,19 @@ Shared by json_sax_dom_parser and json_sax_dom_callback_parser.
|
|||||||
@param[in] ref the object or array that was just created
|
@param[in] ref the object or array that was just created
|
||||||
@return whether parsing should continue (false after reporting out_of_range.408)
|
@return whether parsing should continue (false after reporting out_of_range.408)
|
||||||
*/
|
*/
|
||||||
|
template<typename SAX, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool container_too_large_error(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
||||||
|
{
|
||||||
|
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename SAX, typename BasicJsonType>
|
template<typename SAX, typename BasicJsonType>
|
||||||
bool check_container_size(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
bool check_container_size(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref->max_size()))
|
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref->max_size()))
|
||||||
{
|
{
|
||||||
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
return container_too_large_error(sax, len, kind, ref);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-16
@@ -6954,7 +6954,7 @@ public:
|
|||||||
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
|
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
|
||||||
{
|
{
|
||||||
// avoid undefined behavior
|
// avoid undefined behavior
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::array_index_out_of_range, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
|
throw_array_index_out_of_range(idx, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default case: insert add offset
|
// default case: insert add offset
|
||||||
@@ -6973,7 +6973,7 @@ public:
|
|||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
default:
|
default:
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::patch_add_parent_not_container, detail::concat("cannot add value: the JSON Patch 'add' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
detail::throw_patch_add_parent(parent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -6997,7 +6997,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::key_not_found, detail::concat("key '", last_path, "' not found"), this));
|
throw_key_not_found(last_path, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (parent.is_array())
|
else if (parent.is_array())
|
||||||
@@ -7009,7 +7009,7 @@ public:
|
|||||||
{
|
{
|
||||||
// the parent of a "remove" target must be an object or array
|
// the parent of a "remove" target must be an object or array
|
||||||
// (see #5396)
|
// (see #5396)
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::patch_remove_parent_not_container, detail::concat("cannot remove value: the JSON Patch 'remove' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
detail::throw_patch_remove_parent(parent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7040,7 +7040,7 @@ public:
|
|||||||
// type check: top level value must be an array
|
// type check: top level value must be an array
|
||||||
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_not_an_array, 0, "JSON patch must be an array of objects", &json_patch));
|
detail::throw_patch_not_an_array(json_patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate and apply the operations
|
// iterate and apply the operations
|
||||||
@@ -7054,21 +7054,16 @@ public:
|
|||||||
// find value
|
// find value
|
||||||
auto it = val.m_data.m_value.object->find(member);
|
auto it = val.m_data.m_value.object->find(member);
|
||||||
|
|
||||||
// context-sensitive error message
|
|
||||||
const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
|
|
||||||
|
|
||||||
// check if the desired value is present
|
// check if the desired value is present
|
||||||
if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
|
if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
detail::throw_patch_missing_member(op, member, false, val);
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_invalid_operation, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the result is of type string
|
// check if the result is of type string
|
||||||
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
detail::throw_patch_missing_member(op, member, true, val);
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_invalid_operation, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no error: return value
|
// no error: return value
|
||||||
@@ -7078,7 +7073,7 @@ public:
|
|||||||
// type check: every element of the array must be an object
|
// type check: every element of the array must be an object
|
||||||
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_not_an_array, 0, "JSON patch must be an array of objects", &val));
|
detail::throw_patch_not_an_array(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect mandatory members
|
// collect mandatory members
|
||||||
@@ -7114,7 +7109,7 @@ public:
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(is_proper_prefix(from_ptr, ptr)))
|
if (JSON_HEDLEY_UNLIKELY(is_proper_prefix(from_ptr, ptr)))
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::patch_move_into_child, detail::concat("cannot move value: 'from' path '", from_path, "' is a proper prefix of 'path' '", path, "'"), &result));
|
detail::throw_patch_move_into_child(from_path, path, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the "from" location must exist - use at()
|
// the "from" location must exist - use at()
|
||||||
@@ -7160,7 +7155,7 @@ public:
|
|||||||
// throw an exception if the test fails
|
// throw an exception if the test fails
|
||||||
if (JSON_HEDLEY_UNLIKELY(!success))
|
if (JSON_HEDLEY_UNLIKELY(!success))
|
||||||
{
|
{
|
||||||
JSON_THROW(other_error::create(detail::exception_id::patch_test_failed, detail::concat("unsuccessful: ", val.dump()), &val));
|
detail::throw_patch_test_failed(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -7171,7 +7166,7 @@ public:
|
|||||||
{
|
{
|
||||||
// op must be "add", "remove", "replace", "move", "copy", or
|
// op must be "add", "remove", "replace", "move", "copy", or
|
||||||
// "test"
|
// "test"
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_invalid_operation, 0, detail::concat("operation value '", op, "' is invalid"), &val));
|
detail::throw_patch_invalid_operation(op, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+167
-50
@@ -5672,6 +5672,65 @@ JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_literal(const exceptio
|
|||||||
JSON_THROW(ExceptionType::create(id_, what_arg, context));
|
JSON_THROW(ExceptionType::create(id_, what_arg, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSON Patch errors; constructed out of line so that patch_inplace() does not carry them
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_add_parent(const BasicJsonType& parent)
|
||||||
|
{
|
||||||
|
static_cast<void>(parent);
|
||||||
|
JSON_THROW(out_of_range::create(exception_id::patch_add_parent_not_container, concat("cannot add value: the JSON Patch 'add' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_remove_parent(const BasicJsonType& parent)
|
||||||
|
{
|
||||||
|
static_cast<void>(parent);
|
||||||
|
JSON_THROW(out_of_range::create(exception_id::patch_remove_parent_not_container, concat("cannot remove value: the JSON Patch 'remove' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_not_an_array(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
static_cast<void>(j);
|
||||||
|
JSON_THROW(parse_error::create(exception_id::patch_not_an_array, 0, "JSON patch must be an array of objects", &j));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_missing_member(const StringType& op, const StringType& member, const bool string_type, const BasicJsonType& val)
|
||||||
|
{
|
||||||
|
static_cast<void>(op);
|
||||||
|
static_cast<void>(member);
|
||||||
|
static_cast<void>(string_type);
|
||||||
|
static_cast<void>(val);
|
||||||
|
// context-sensitive error message
|
||||||
|
const std::string error_msg = (op == "op") ? std::string("operation") : concat("operation '", op, '\'');
|
||||||
|
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat(error_msg, string_type ? " must have string member '" : " must have member '", member, "'"), &val));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_move_into_child(const StringType& from_path, const StringType& path, const BasicJsonType& result)
|
||||||
|
{
|
||||||
|
static_cast<void>(from_path);
|
||||||
|
static_cast<void>(path);
|
||||||
|
static_cast<void>(result);
|
||||||
|
JSON_THROW(out_of_range::create(exception_id::patch_move_into_child, concat("cannot move value: 'from' path '", from_path, "' is a proper prefix of 'path' '", path, "'"), &result));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_test_failed(const BasicJsonType& val)
|
||||||
|
{
|
||||||
|
static_cast<void>(val);
|
||||||
|
JSON_THROW(other_error::create(exception_id::patch_test_failed, concat("unsuccessful: ", val.dump()), &val));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_invalid_operation(const StringType& op, const BasicJsonType& val)
|
||||||
|
{
|
||||||
|
static_cast<void>(op);
|
||||||
|
static_cast<void>(val);
|
||||||
|
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat("operation value '", op, "' is invalid"), &val));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
@@ -13497,12 +13556,19 @@ Shared by json_sax_dom_parser and json_sax_dom_callback_parser.
|
|||||||
@param[in] ref the object or array that was just created
|
@param[in] ref the object or array that was just created
|
||||||
@return whether parsing should continue (false after reporting out_of_range.408)
|
@return whether parsing should continue (false after reporting out_of_range.408)
|
||||||
*/
|
*/
|
||||||
|
template<typename SAX, typename BasicJsonType>
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool container_too_large_error(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
||||||
|
{
|
||||||
|
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename SAX, typename BasicJsonType>
|
template<typename SAX, typename BasicJsonType>
|
||||||
bool check_container_size(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
bool check_container_size(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref->max_size()))
|
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref->max_size()))
|
||||||
{
|
{
|
||||||
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
return container_too_large_error(sax, len, kind, ref);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -14797,7 +14863,7 @@ class binary_reader
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_end_of_input, concat("expected end of input; last byte: 0x", get_token_string()), "value");
|
return last_byte_error(exception_id::unexpected_end_of_input, "expected end of input", "value", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14919,7 +14985,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document");
|
return bson_document_size_error(document_size, chars_read - document_start);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -15111,7 +15177,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("string length must be at least 1, is ", std::to_string(len)), "string");
|
return bson_length_error("string length must be at least 1, is ", len, "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
||||||
@@ -15141,7 +15207,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary");
|
return bson_length_error("byte array length cannot be negative, is ", len, "binary");
|
||||||
}
|
}
|
||||||
|
|
||||||
// All BSON binary values have a subtype
|
// All BSON binary values have a subtype
|
||||||
@@ -15231,9 +15297,7 @@ class binary_reader
|
|||||||
|
|
||||||
default: // anything else is not supported (yet)
|
default: // anything else is not supported (yet)
|
||||||
{
|
{
|
||||||
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
return bson_unsupported_type_error(element_type_parse_position, element_type);
|
||||||
return sax->parse_error(element_type_parse_position, cr_str,
|
|
||||||
parse_error::create(exception_id::bson_unsupported_type, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15662,6 +15726,7 @@ class binary_reader
|
|||||||
@param[in] context parsing context for the error message
|
@param[in] context parsing context for the error message
|
||||||
@return whether the SAX consumer accepts the parse error
|
@return whether the SAX consumer accepts the parse error
|
||||||
*/
|
*/
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("indefinite-length ", type_name, " is not allowed inside indefinite-length ", type_name, "; last byte: 0x", get_token_string()), context);
|
return last_byte_error(exception_id::invalid_string_or_size, concat("indefinite-length ", type_name, " is not allowed inside indefinite-length ", type_name, "; last byte: 0x", get_token_string()), context);
|
||||||
@@ -15741,7 +15806,7 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0x60-0x7B)", inside_indefinite ? "" : " or indefinite string type (0x7F)", "; last byte: 0x", get_token_string()), "string");
|
return last_byte_error(exception_id::invalid_string_or_size, "expected length specification (0x60-0x7B)", "string", inside_indefinite ? "" : " or indefinite string type (0x7F)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15871,7 +15936,7 @@ class binary_reader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("only string keys are supported, but found ", found, "; last byte: 0x", get_token_string()), "object key");
|
return last_byte_error(exception_id::invalid_string_or_size, "only string keys are supported, but found ", "object key", found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -15952,7 +16017,7 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0x40-0x5B)", inside_indefinite ? "" : " or indefinite binary array type (0x5F)", "; last byte: 0x", get_token_string()), "binary");
|
return last_byte_error(exception_id::invalid_string_or_size, "expected length specification (0x40-0x5B)", "binary", inside_indefinite ? "" : " or indefinite binary array type (0x5F)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16098,8 +16163,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return container_size_error(context);
|
||||||
exception_message(concat("excessive ", context, " size"), "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
result = conditional_static_cast<std::size_t>(len);
|
result = conditional_static_cast<std::size_t>(len);
|
||||||
return true;
|
return true;
|
||||||
@@ -16667,7 +16731,7 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", get_token_string()), "string");
|
return last_byte_error(exception_id::invalid_string_or_size, "expected length specification (0xA0-0xBF, 0xD9-0xDB)", "string", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16759,7 +16823,7 @@ class binary_reader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("only string keys are supported, but found ", found, "; last byte: 0x", get_token_string()), "object key");
|
return last_byte_error(exception_id::invalid_string_or_size, "only string keys are supported, but found ", "object key", found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -17257,8 +17321,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return out_of_range_error(exception_id::container_too_large, "integer value overflow", "size");
|
||||||
exception_message("integer value overflow", "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
|
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
|
||||||
return true;
|
return true;
|
||||||
@@ -17355,8 +17418,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (!value_in_range_of<std::size_t>(number))
|
if (!value_in_range_of<std::size_t>(number))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return out_of_range_error(exception_id::container_too_large, "integer value overflow", "size");
|
||||||
exception_message("integer value overflow", "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
result = detail::conditional_static_cast<std::size_t>(number);
|
result = detail::conditional_static_cast<std::size_t>(number);
|
||||||
return true;
|
return true;
|
||||||
@@ -17434,7 +17496,7 @@ class binary_reader
|
|||||||
// or SIZE_MAX.
|
// or SIZE_MAX.
|
||||||
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
return out_of_range_error(exception_id::container_too_large, "excessive ndarray size caused overflow", "size");
|
||||||
}
|
}
|
||||||
result *= i;
|
result *= i;
|
||||||
// the pre-check above already rules out result becoming 0
|
// the pre-check above already rules out result becoming 0
|
||||||
@@ -17443,7 +17505,7 @@ class binary_reader
|
|||||||
// unknown-size container (see get_ubjson_size_type())
|
// unknown-size container (see get_ubjson_size_type())
|
||||||
if (result == npos)
|
if (result == npos)
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
return out_of_range_error(exception_id::container_too_large, "excessive ndarray size caused overflow", "size");
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
||||||
{
|
{
|
||||||
@@ -17493,7 +17555,7 @@ class binary_reader
|
|||||||
if (input_format == input_format_t::bjdata
|
if (input_format == input_format_t::bjdata
|
||||||
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
return optimized_type_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
||||||
@@ -17508,7 +17570,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("expected '#' after type information; last byte: 0x", get_token_string()), "size");
|
return last_byte_error(exception_id::unexpected_byte, "expected '#' after type information", "size", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
||||||
@@ -17659,7 +17721,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", get_token_string()), "char");
|
return last_byte_error(exception_id::invalid_string_or_size, "byte after 'C' must be in range 0x00..0x7F", "char", "");
|
||||||
}
|
}
|
||||||
string_t s(1, static_cast<typename string_t::value_type>(current));
|
string_t s(1, static_cast<typename string_t::value_type>(current));
|
||||||
return sax->string(s);
|
return sax->string(s);
|
||||||
@@ -17743,8 +17805,7 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY((size_and_type.second == 'Z' || size_and_type.second == 'T' || size_and_type.second == 'F')
|
if (JSON_HEDLEY_UNLIKELY((size_and_type.second == 'Z' || size_and_type.second == 'T' || size_and_type.second == 'F')
|
||||||
&& size_and_type.first > max_valueless_container_size))
|
&& size_and_type.first > max_valueless_container_size))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return out_of_range_error(exception_id::container_too_large, "excessive array size", "size");
|
||||||
exception_message("excessive array size", "size"), nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!enter_array(size_and_type.first, size_and_type.second)))
|
if (JSON_HEDLEY_UNLIKELY(!enter_array(size_and_type.first, size_and_type.second)))
|
||||||
@@ -18456,7 +18517,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
// in case of failure, advance position by 1 to report the failing location
|
// in case of failure, advance position by 1 to report the failing location
|
||||||
++chars_read;
|
++chars_read;
|
||||||
sax->parse_error(chars_read, "<end of file>", parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
static_cast<void>(report_eof(context));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -18609,8 +18670,7 @@ class binary_reader
|
|||||||
const auto result = static_cast<number_float_t>(number);
|
const auto result = static_cast<number_float_t>(number);
|
||||||
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(),
|
return out_of_range_error(exception_id::number_overflow, "number overflow", "value");
|
||||||
out_of_range::create(exception_id::number_overflow, exception_message("number overflow", "value"), nullptr));
|
|
||||||
}
|
}
|
||||||
return sax->number_float(result, "");
|
return sax->number_float(result, "");
|
||||||
}
|
}
|
||||||
@@ -18825,22 +18885,82 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, "<end of file>",
|
return report_eof(context);
|
||||||
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief reports an unexpected end of input (out of line to keep the exception
|
||||||
|
construction out of the hot reading functions)
|
||||||
|
@param[in] context further context information (for diagnostics)
|
||||||
|
@return the result of the SAX parser's parse_error()
|
||||||
|
*/
|
||||||
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool report_eof(const char* context) const
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, "<end of file>",
|
||||||
|
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief reports an out_of_range error at the last read byte (out of line)
|
||||||
|
*/
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool out_of_range_error(const exception_id id_, const char* detail, const char* context) const
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(id_, exception_message(detail, context), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool container_size_error(const char* what) const
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||||
|
exception_message(concat("excessive ", what, " size"), "size"), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool optimized_type_error() const
|
||||||
|
{
|
||||||
|
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool bson_length_error(const char* prefix, const NumberType len, const char* context) const
|
||||||
|
{
|
||||||
|
return last_byte_error(exception_id::unexpected_byte, concat(prefix, std::to_string(len)), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool bson_document_size_error(const std::int32_t document_size, const std::size_t bytes_read) const
|
||||||
|
{
|
||||||
|
return last_byte_error(exception_id::unexpected_byte, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(bytes_read), ")"), "document");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool bson_unsupported_type_error(const std::size_t position, const char element_type) const
|
||||||
|
{
|
||||||
|
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
||||||
|
return sax->parse_error(position, cr_str,
|
||||||
|
parse_error::create(exception_id::bson_unsupported_type, position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief reports a parse error at the last read byte
|
@brief reports a parse error at the last read byte
|
||||||
@param[in] id_ the id of the parse_error exception
|
@param[in] id_ the id of the parse_error exception
|
||||||
@param[in] detail a detailed error message
|
@param[in] detail a detailed error message
|
||||||
@param[in] context further context information
|
@param[in] context further context information
|
||||||
|
@param[in] tail optional text appended to the detail, followed by "; last byte: 0x<token>"
|
||||||
@return the result of the SAX parser's parse_error()
|
@return the result of the SAX parser's parse_error()
|
||||||
*/
|
*/
|
||||||
bool last_byte_error(const exception_id id_, const std::string& detail, const std::string& context) const
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool last_byte_error(const exception_id id_, const std::string& detail, const char* context, const char* tail = nullptr) const
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), parse_error::create(id_, chars_read, exception_message(detail, context), nullptr));
|
// with a tail, the message reads "<detail><tail>; last byte: 0x<token>"
|
||||||
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(id_, chars_read,
|
||||||
|
exception_message(tail == nullptr ? detail : concat(detail, tail, "; last byte: 0x", get_token_string()), context), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -18849,7 +18969,8 @@ class binary_reader
|
|||||||
@param[in] context further context information
|
@param[in] context further context information
|
||||||
@return the result of the SAX parser's parse_error()
|
@return the result of the SAX parser's parse_error()
|
||||||
*/
|
*/
|
||||||
bool unexpected_byte(const char* detail, const std::string& context) const
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
|
bool unexpected_byte(const char* detail, const char* context) const
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat(detail, ": 0x", get_token_string()), context);
|
return last_byte_error(exception_id::unexpected_byte, concat(detail, ": 0x", get_token_string()), context);
|
||||||
}
|
}
|
||||||
@@ -18860,6 +18981,7 @@ class binary_reader
|
|||||||
@param[in] context further context information
|
@param[in] context further context information
|
||||||
@return the result of the SAX parser's parse_error()
|
@return the result of the SAX parser's parse_error()
|
||||||
*/
|
*/
|
||||||
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
bool length_type_error(const char* position, const char* context) const
|
bool length_type_error(const char* position, const char* context) const
|
||||||
{
|
{
|
||||||
const char* types = input_format == input_format_t::bjdata ? "U, i, u, I, m, l, M, L" : "U, i, I, l, L";
|
const char* types = input_format == input_format_t::bjdata ? "U, i, u, I, m, l, M, L" : "U, i, I, l, L";
|
||||||
@@ -36647,7 +36769,7 @@ public:
|
|||||||
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
|
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
|
||||||
{
|
{
|
||||||
// avoid undefined behavior
|
// avoid undefined behavior
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::array_index_out_of_range, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
|
throw_array_index_out_of_range(idx, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default case: insert add offset
|
// default case: insert add offset
|
||||||
@@ -36666,7 +36788,7 @@ public:
|
|||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
default:
|
default:
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::patch_add_parent_not_container, detail::concat("cannot add value: the JSON Patch 'add' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
detail::throw_patch_add_parent(parent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -36690,7 +36812,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::key_not_found, detail::concat("key '", last_path, "' not found"), this));
|
throw_key_not_found(last_path, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (parent.is_array())
|
else if (parent.is_array())
|
||||||
@@ -36702,7 +36824,7 @@ public:
|
|||||||
{
|
{
|
||||||
// the parent of a "remove" target must be an object or array
|
// the parent of a "remove" target must be an object or array
|
||||||
// (see #5396)
|
// (see #5396)
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::patch_remove_parent_not_container, detail::concat("cannot remove value: the JSON Patch 'remove' target's parent is of type ", parent.type_name(), ", but must be an object or array"), &parent));
|
detail::throw_patch_remove_parent(parent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -36733,7 +36855,7 @@ public:
|
|||||||
// type check: top level value must be an array
|
// type check: top level value must be an array
|
||||||
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_not_an_array, 0, "JSON patch must be an array of objects", &json_patch));
|
detail::throw_patch_not_an_array(json_patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate and apply the operations
|
// iterate and apply the operations
|
||||||
@@ -36747,21 +36869,16 @@ public:
|
|||||||
// find value
|
// find value
|
||||||
auto it = val.m_data.m_value.object->find(member);
|
auto it = val.m_data.m_value.object->find(member);
|
||||||
|
|
||||||
// context-sensitive error message
|
|
||||||
const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
|
|
||||||
|
|
||||||
// check if the desired value is present
|
// check if the desired value is present
|
||||||
if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
|
if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
detail::throw_patch_missing_member(op, member, false, val);
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_invalid_operation, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the result is of type string
|
// check if the result is of type string
|
||||||
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
detail::throw_patch_missing_member(op, member, true, val);
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_invalid_operation, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no error: return value
|
// no error: return value
|
||||||
@@ -36771,7 +36888,7 @@ public:
|
|||||||
// type check: every element of the array must be an object
|
// type check: every element of the array must be an object
|
||||||
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_not_an_array, 0, "JSON patch must be an array of objects", &val));
|
detail::throw_patch_not_an_array(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect mandatory members
|
// collect mandatory members
|
||||||
@@ -36807,7 +36924,7 @@ public:
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(is_proper_prefix(from_ptr, ptr)))
|
if (JSON_HEDLEY_UNLIKELY(is_proper_prefix(from_ptr, ptr)))
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(detail::exception_id::patch_move_into_child, detail::concat("cannot move value: 'from' path '", from_path, "' is a proper prefix of 'path' '", path, "'"), &result));
|
detail::throw_patch_move_into_child(from_path, path, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the "from" location must exist - use at()
|
// the "from" location must exist - use at()
|
||||||
@@ -36853,7 +36970,7 @@ public:
|
|||||||
// throw an exception if the test fails
|
// throw an exception if the test fails
|
||||||
if (JSON_HEDLEY_UNLIKELY(!success))
|
if (JSON_HEDLEY_UNLIKELY(!success))
|
||||||
{
|
{
|
||||||
JSON_THROW(other_error::create(detail::exception_id::patch_test_failed, detail::concat("unsuccessful: ", val.dump()), &val));
|
detail::throw_patch_test_failed(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -36864,7 +36981,7 @@ public:
|
|||||||
{
|
{
|
||||||
// op must be "add", "remove", "replace", "move", "copy", or
|
// op must be "add", "remove", "replace", "move", "copy", or
|
||||||
// "test"
|
// "test"
|
||||||
JSON_THROW(parse_error::create(detail::exception_id::patch_invalid_operation, 0, detail::concat("operation value '", op, "' is invalid"), &val));
|
detail::throw_patch_invalid_operation(op, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// The exceptions in hot core functions are constructed out of line. These tests pin the
|
// The exceptions in hot core functions are constructed out of line. These tests pin the
|
||||||
// exact what() texts of the sites that moved, so the refactoring cannot change them.
|
// exact what() texts of the sites that moved, so the refactoring cannot change them.
|
||||||
|
|
||||||
@@ -91,4 +93,43 @@ TEST_CASE("exception messages of out-of-line throw sites")
|
|||||||
CHECK_MSG(obj.insert(arr.begin(), arr.end()), "[json.exception.invalid_iterator.202] iterators first and last must point to objects");
|
CHECK_MSG(obj.insert(arr.begin(), arr.end()), "[json.exception.invalid_iterator.202] iterators first and last must point to objects");
|
||||||
CHECK_MSG(obj.update(arr.begin(), arr2.end()), "[json.exception.invalid_iterator.210] iterators do not fit");
|
CHECK_MSG(obj.update(arr.begin(), arr2.end()), "[json.exception.invalid_iterator.210] iterators do not fit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("patch")
|
||||||
|
{
|
||||||
|
const auto patch_msg = [](const char* doc, const char* patch)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json d = json::parse(doc);
|
||||||
|
d.patch(json::parse(patch));
|
||||||
|
}
|
||||||
|
catch (const json::exception& e)
|
||||||
|
{
|
||||||
|
// with JSON_DIAGNOSTICS, what() names the offending value like "(/0) "; drop it
|
||||||
|
std::string msg = e.what();
|
||||||
|
const auto pos = msg.find(" (/");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
msg.erase(pos + 1, msg.find(") ", pos) - pos + 1);
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
};
|
||||||
|
|
||||||
|
CHECK(patch_msg("{}", "{}") == "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects");
|
||||||
|
CHECK(patch_msg("{}", "[1]") == "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects");
|
||||||
|
CHECK(patch_msg("{}", "[{}]") == "[json.exception.parse_error.105] parse error: operation must have member 'op'");
|
||||||
|
CHECK(patch_msg("{}", "[{\"op\":1}]") == "[json.exception.parse_error.105] parse error: operation must have string member 'op'");
|
||||||
|
CHECK(patch_msg("{}", "[{\"op\":\"add\"}]") == "[json.exception.parse_error.105] parse error: operation 'add' must have member 'path'");
|
||||||
|
CHECK(patch_msg("{}", "[{\"op\":\"add\",\"path\":1}]") == "[json.exception.parse_error.105] parse error: operation 'add' must have string member 'path'");
|
||||||
|
CHECK(patch_msg("{}", "[{\"op\":\"foo\",\"path\":\"\"}]") == "[json.exception.parse_error.105] parse error: operation value 'foo' is invalid");
|
||||||
|
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"remove\",\"path\":\"/b\"}]") == "[json.exception.out_of_range.403] key 'b' not found");
|
||||||
|
CHECK(patch_msg("[1]", "[{\"op\":\"add\",\"path\":\"/5\",\"value\":0}]") == "[json.exception.out_of_range.401] array index 5 is out of range");
|
||||||
|
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"add\",\"path\":\"/a/b\",\"value\":0}]") == "[json.exception.out_of_range.411] cannot add value: the JSON Patch 'add' target's parent is of type number, but must be an object or array");
|
||||||
|
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"remove\",\"path\":\"/a/b\"}]") == "[json.exception.out_of_range.413] cannot remove value: the JSON Patch 'remove' target's parent is of type number, but must be an object or array");
|
||||||
|
CHECK(patch_msg("{\"a\":{}}", "[{\"op\":\"move\",\"from\":\"/a\",\"path\":\"/a/b\"}]") == "[json.exception.out_of_range.414] cannot move value: 'from' path '/a' is a proper prefix of 'path' '/a/b'");
|
||||||
|
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"test\",\"path\":\"/a\",\"value\":2}]") == "[json.exception.other_error.501] unsuccessful: {\"op\":\"test\",\"path\":\"/a\",\"value\":2}");
|
||||||
|
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"move\",\"path\":\"/a\"}]") == "[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user