mirror of
https://github.com/nlohmann/json.git
synced 2026-10-12 09:27:13 +00:00
Merge remote-tracking branch 'origin/develop' into claude/fix-issue-3989-db7e45
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
116 files changed
+4199
-2405
No files matched your search
@@ -12,7 +12,6 @@
|
||||
#include <cmath> // ldexp
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t, uintmax_t
|
||||
#include <cstdio> // snprintf
|
||||
#include <cstring> // memcpy
|
||||
#include <iterator> // back_inserter
|
||||
#include <limits> // numeric_limits
|
||||
@@ -224,8 +223,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
|
||||
exception_message(concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_end_of_input, concat("expected end of input; last byte: 0x", get_token_string()), "value");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,8 +354,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||
{
|
||||
static_cast<void>(report_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
|
||||
exception_message(concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr)));
|
||||
static_cast<void>(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 repair_requested();
|
||||
}
|
||||
return true;
|
||||
@@ -681,9 +678,7 @@ class binary_reader
|
||||
{
|
||||
// the end of the element is lost (see resync)
|
||||
skip_requested = true;
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("string length must be at least 1, is ", std::to_string(len)), "string");
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
||||
@@ -693,10 +688,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(get() != 0x00))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
static_cast<void>(report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message("BSON string is not null-terminated",
|
||||
"string"), nullptr)));
|
||||
static_cast<void>(last_byte_error(exception_id::unexpected_byte, "BSON string is not null-terminated", "string"));
|
||||
// when recovering, a byte in place of the terminator is dropped;
|
||||
// the end of the input is not
|
||||
return current != char_traits<char_type>::eof() && repair_requested();
|
||||
@@ -721,9 +713,7 @@ class binary_reader
|
||||
{
|
||||
// the end of the element is lost (see resync)
|
||||
skip_requested = true;
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary");
|
||||
}
|
||||
|
||||
// All BSON binary values have a subtype
|
||||
@@ -813,11 +803,9 @@ class binary_reader
|
||||
|
||||
default: // anything else is not supported (yet)
|
||||
{
|
||||
std::array<char, 3> cr{{}};
|
||||
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||
const std::string cr_str{cr.data()};
|
||||
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
||||
static_cast<void>(report_error(element_type_parse_position, cr_str,
|
||||
parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)));
|
||||
parse_error::create(exception_id::bson_unsupported_type, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)));
|
||||
return skip_unsupported_bson_element(element_type);
|
||||
}
|
||||
}
|
||||
@@ -1142,9 +1130,7 @@ class binary_reader
|
||||
{
|
||||
if (tag_handler == cbor_tag_handler_t::error)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
static_cast<void>(report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)));
|
||||
static_cast<void>(unexpected_byte("invalid byte", "value"));
|
||||
if (!repair_requested())
|
||||
{
|
||||
return false;
|
||||
@@ -1170,9 +1156,7 @@ class binary_reader
|
||||
{
|
||||
case cbor_tag_handler_t::error:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
static_cast<void>(report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)));
|
||||
static_cast<void>(unexpected_byte("invalid byte", "value"));
|
||||
if (!repair_requested())
|
||||
{
|
||||
return false;
|
||||
@@ -1253,12 +1237,10 @@ class binary_reader
|
||||
|
||||
default: // anything else (0xFF is handled inside the other types)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
// the simple values other than false, true, and null (0xE0..0xF3,
|
||||
// 0xF7 for undefined, and 0xF8 followed by a byte) are complete
|
||||
const bool simple_value = (current >= 0xE0 && current <= 0xF3) || current == 0xF7 || current == 0xF8;
|
||||
static_cast<void>(report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)));
|
||||
static_cast<void>(unexpected_byte("invalid byte", "value"));
|
||||
if (!simple_value || !repair_requested())
|
||||
{
|
||||
return false;
|
||||
@@ -1279,10 +1261,7 @@ class binary_reader
|
||||
*/
|
||||
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("indefinite-length ", type_name,
|
||||
" is not allowed inside indefinite-length ", type_name, "; last byte: 0x", last_token), context), nullptr));
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1359,9 +1338,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("expected length specification (0x60-0x7B)", inside_indefinite ? "" : " or indefinite string type (0x7F)", "; last byte: 0x", last_token), "string"), nullptr));
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1495,9 +1472,7 @@ class binary_reader
|
||||
// a key that begins an item is skipped with its value when recovering
|
||||
// (see resync); a break stop code or a reserved byte begins none
|
||||
skip_requested = is_cbor_item_head(static_cast<unsigned int>(current));
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
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");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1578,9 +1553,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("expected length specification (0x40-0x5B)", inside_indefinite ? "" : " or indefinite binary array type (0x5F)", "; last byte: 0x", last_token), "binary"), nullptr));
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1726,7 +1699,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
exception_message(concat("excessive ", context, " size"), "size"), nullptr));
|
||||
}
|
||||
result = conditional_static_cast<std::size_t>(len);
|
||||
@@ -1876,9 +1849,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_cbor_item_head(static_cast<unsigned int>(current))))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
const auto major_type = static_cast<unsigned int>(current) >> 5u;
|
||||
@@ -2336,9 +2307,7 @@ class binary_reader
|
||||
|
||||
default: // anything else
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2419,9 +2388,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2516,9 +2483,7 @@ class binary_reader
|
||||
|
||||
// the key is skipped with its value when recovering (see resync)
|
||||
skip_requested = true;
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
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");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2845,9 +2810,7 @@ class binary_reader
|
||||
|
||||
default: // 0xC1, which is never used
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2976,8 +2939,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
|
||||
exception_message("string length must not be negative", "string"), nullptr));
|
||||
return last_byte_error(exception_id::invalid_string_or_size, "string length must not be negative", "string");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3077,18 +3039,7 @@ class binary_reader
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto last_token = get_token_string();
|
||||
std::string message;
|
||||
|
||||
if (input_format != input_format_t::bjdata)
|
||||
{
|
||||
message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
|
||||
}
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "string"), nullptr));
|
||||
return length_type_error("", "string");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3173,12 +3124,11 @@ class binary_reader
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(number < 0))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
|
||||
exception_message("count in an optimized container must be positive", "size"), nullptr));
|
||||
return last_byte_error(exception_id::invalid_string_or_size, "count in an optimized container must be positive", "size");
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
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
|
||||
@@ -3276,7 +3226,7 @@ class binary_reader
|
||||
}
|
||||
if (!value_in_range_of<std::size_t>(number))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
exception_message("integer value overflow", "size"), nullptr));
|
||||
}
|
||||
result = detail::conditional_static_cast<std::size_t>(number);
|
||||
@@ -3291,7 +3241,7 @@ class binary_reader
|
||||
}
|
||||
if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message("ndarray dimensional vector is not allowed", "size"), nullptr));
|
||||
return last_byte_error(exception_id::invalid_string_or_size, "ndarray dimensional vector is not allowed", "size");
|
||||
}
|
||||
std::vector<size_t> dim;
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
|
||||
@@ -3329,9 +3279,7 @@ class binary_reader
|
||||
const char* type_name = bjd_type_name(ndarray_dtype);
|
||||
if (JSON_HEDLEY_UNLIKELY(type_name == nullptr))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message("invalid byte: 0x" + last_token, "type"), nullptr));
|
||||
return unexpected_byte("invalid byte", "type");
|
||||
}
|
||||
|
||||
string_t type_key = "_ArrayType_";
|
||||
@@ -3360,7 +3308,7 @@ class binary_reader
|
||||
// or SIZE_MAX.
|
||||
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||
}
|
||||
result *= i;
|
||||
// the pre-check above already rules out result becoming 0
|
||||
@@ -3369,7 +3317,7 @@ class binary_reader
|
||||
// unknown-size container (see get_ubjson_size_type())
|
||||
if (result == npos)
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
||||
{
|
||||
@@ -3387,18 +3335,7 @@ class binary_reader
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto last_token = get_token_string();
|
||||
std::string message;
|
||||
|
||||
if (input_format != input_format_t::bjdata)
|
||||
{
|
||||
message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
|
||||
}
|
||||
return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "size"), nullptr));
|
||||
return length_type_error(" after '#'", "size");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3431,9 +3368,7 @@ class binary_reader
|
||||
if (input_format == input_format_t::bjdata
|
||||
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
||||
@@ -3448,9 +3383,7 @@ class binary_reader
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("expected '#' after type information; last byte: 0x", get_token_string()), "size");
|
||||
}
|
||||
|
||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
||||
@@ -3469,8 +3402,7 @@ class binary_reader
|
||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
|
||||
if (input_format == input_format_t::bjdata && is_ndarray && !inside_ndarray)
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
|
||||
exception_message("ndarray requires both type and size", "size"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_byte, "ndarray requires both type and size", "size");
|
||||
}
|
||||
return is_error;
|
||||
}
|
||||
@@ -3602,9 +3534,7 @@ class binary_reader
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
static_cast<void>(report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)));
|
||||
static_cast<void>(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"));
|
||||
if (!repair_requested())
|
||||
{
|
||||
return false;
|
||||
@@ -3633,8 +3563,7 @@ class binary_reader
|
||||
default: // anything else
|
||||
break;
|
||||
}
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message("invalid byte: 0x" + last_token, "value"), nullptr));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3699,7 +3628,7 @@ class binary_reader
|
||||
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))
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||
return report_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
exception_message("excessive array size", "size"), nullptr));
|
||||
}
|
||||
|
||||
@@ -3735,9 +3664,7 @@ class binary_reader
|
||||
// do not accept ND-array size in objects in BJData
|
||||
if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message("BJData object does not support ND-array size in optimized format", "object"), nullptr));
|
||||
return last_byte_error(exception_id::unexpected_byte, "BJData object does not support ND-array size in optimized format", "object");
|
||||
}
|
||||
|
||||
if (size_and_type.first != npos)
|
||||
@@ -3774,7 +3701,7 @@ class binary_reader
|
||||
// the lexer would stop at a NUL and accept the digits before it
|
||||
if (JSON_HEDLEY_UNLIKELY(current == '\0'))
|
||||
{
|
||||
static_cast<void>(report_error(chars_read, "00", parse_error::create(115, chars_read,
|
||||
static_cast<void>(report_error(chars_read, "00", parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
||||
exception_message("invalid number text; last byte: 0x00", "high-precision number"), nullptr)));
|
||||
// when recovering, the number ends at the NUL, as it would in
|
||||
// JSON text, and the rest of its bytes are skipped
|
||||
@@ -3794,7 +3721,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
|
||||
{
|
||||
static_cast<void>(report_error(chars_read, number_string, parse_error::create(115, chars_read,
|
||||
static_cast<void>(report_error(chars_read, number_string, parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
||||
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)));
|
||||
return recover_high_precision_number(number_vector);
|
||||
}
|
||||
@@ -3815,7 +3742,7 @@ class binary_reader
|
||||
static_cast<void>(report_error(
|
||||
chars_read,
|
||||
number_string,
|
||||
out_of_range::create(406, concat("number overflow parsing '", number_string, '\''), nullptr)));
|
||||
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", number_string, '\''), nullptr)));
|
||||
if (!repair_requested())
|
||||
{
|
||||
return false;
|
||||
@@ -3841,7 +3768,7 @@ class binary_reader
|
||||
case token_type::end_of_input:
|
||||
case token_type::literal_or_value:
|
||||
default:
|
||||
static_cast<void>(report_error(chars_read, number_string, parse_error::create(115, chars_read,
|
||||
static_cast<void>(report_error(chars_read, number_string, parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
||||
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)));
|
||||
return recover_high_precision_number(number_vector);
|
||||
}
|
||||
@@ -3966,20 +3893,6 @@ class binary_reader
|
||||
return 0x80 <= c && c <= 0xBF;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief report a parse error at the last read byte
|
||||
|
||||
@param[in] detail a detailed error message
|
||||
@param[in] context further context information
|
||||
@return false
|
||||
*/
|
||||
bool bon8_error(const std::string& detail, const char* context)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return report_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(concat(detail, ": 0x", last_token), context), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief read a BON8 value and everything nested inside it
|
||||
|
||||
@@ -4203,7 +4116,7 @@ class binary_reader
|
||||
}
|
||||
|
||||
// 0xFE: end of container where a value is expected
|
||||
return bon8_error("invalid byte", "value");
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -4333,7 +4246,7 @@ class binary_reader
|
||||
// an end-of-container marker is no value; any other byte begins one,
|
||||
// and the member is skipped when recovering (see skip_member)
|
||||
skip_requested = byte != 0xFE;
|
||||
return bon8_error("expected a string; last byte", "key");
|
||||
return unexpected_byte("expected a string; last byte", "key");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -4399,7 +4312,7 @@ class binary_reader
|
||||
return skip_bon8_bytes(8);
|
||||
|
||||
case 0xFE: // end of container where a value is expected
|
||||
return bon8_error("invalid byte", "value");
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -4568,7 +4481,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!valid_second))
|
||||
{
|
||||
return bon8_error("invalid UTF-8 byte", "string");
|
||||
return unexpected_byte("invalid UTF-8 byte", "string");
|
||||
}
|
||||
|
||||
result.push_back(static_cast<typename string_t::value_type>(byte));
|
||||
@@ -4582,7 +4495,7 @@ class binary_reader
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_bon8_continuation(current)))
|
||||
{
|
||||
return bon8_error("invalid UTF-8 byte", "string");
|
||||
return unexpected_byte("invalid UTF-8 byte", "string");
|
||||
}
|
||||
result.push_back(static_cast<typename string_t::value_type>(current));
|
||||
}
|
||||
@@ -4627,7 +4540,7 @@ class binary_reader
|
||||
{
|
||||
// in case of failure, advance position by 1 to report the failing location
|
||||
++chars_read;
|
||||
return report_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||
return report_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));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -4780,7 +4693,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
||||
{
|
||||
static_cast<void>(report_error(chars_read, get_token_string(),
|
||||
out_of_range::create(406, exception_message("number overflow", "value"), nullptr)));
|
||||
out_of_range::create(exception_id::number_overflow, exception_message("number overflow", "value"), nullptr)));
|
||||
// when recovering, the number becomes infinity, as in JSON text
|
||||
if (!repair_requested())
|
||||
{
|
||||
@@ -4905,9 +4818,7 @@ class binary_reader
|
||||
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
static_cast<void>(report_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message("invalid string: ill-formed UTF-8 byte", context), nullptr)));
|
||||
static_cast<void>(last_byte_error(exception_id::invalid_string_or_size, "invalid string: ill-formed UTF-8 byte", context));
|
||||
// when recovering, the string is repaired as with
|
||||
// error_handler_t::replace
|
||||
if (!repair_requested())
|
||||
@@ -5303,19 +5214,53 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
||||
{
|
||||
return report_error(chars_read, "<end of file>",
|
||||
parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reports a parse error at the last read byte
|
||||
@param[in] id_ the id of the parse_error exception
|
||||
@param[in] detail a detailed error message
|
||||
@param[in] context further context information
|
||||
@return false, so that the caller stops reading (see report_error)
|
||||
*/
|
||||
bool last_byte_error(const exception_id id_, const std::string& detail, const std::string& context)
|
||||
{
|
||||
return report_error(chars_read, get_token_string(), parse_error::create(id_, chars_read, exception_message(detail, context), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reports the last read byte as unexpected (parse_error.112)
|
||||
@param[in] detail what is wrong with the byte, e.g. "invalid byte"
|
||||
@param[in] context further context information
|
||||
@return false, so that the caller stops reading (see report_error)
|
||||
*/
|
||||
bool unexpected_byte(const char* detail, const std::string& context)
|
||||
{
|
||||
return last_byte_error(exception_id::unexpected_byte, concat(detail, ": 0x", get_token_string()), context);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reports that the last read byte is not a UBJSON/BJData length type (parse_error.113)
|
||||
@param[in] position where the length type was expected, e.g. " after '#'"
|
||||
@param[in] context further context information
|
||||
@return false, so that the caller stops reading (see report_error)
|
||||
*/
|
||||
bool length_type_error(const char* position, const char* context)
|
||||
{
|
||||
const char* types = input_format == input_format_t::bjdata ? "U, i, u, I, m, l, M, L" : "U, i, I, l, L";
|
||||
return last_byte_error(exception_id::invalid_string_or_size,
|
||||
concat("expected length type specification (", types, ")", position, "; last byte: 0x", get_token_string()), context);
|
||||
}
|
||||
|
||||
/*!
|
||||
@return a string representation of the last read byte
|
||||
*/
|
||||
std::string get_token_string() const
|
||||
{
|
||||
std::array<char, 3> cr{{}};
|
||||
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||
return std::string{cr.data()};
|
||||
return hex_byte(static_cast<std::uint8_t>(current));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -581,7 +581,7 @@ class wide_string_input_adapter
|
||||
template<class T>
|
||||
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
||||
{
|
||||
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::unexpected_byte, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -793,7 +793,7 @@ inline file_input_adapter input_adapter(std::FILE* file)
|
||||
{
|
||||
if (file == nullptr)
|
||||
{
|
||||
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
}
|
||||
return file_input_adapter(file);
|
||||
}
|
||||
@@ -802,7 +802,7 @@ inline input_stream_adapter input_adapter(std::istream& stream)
|
||||
{
|
||||
if (stream.rdbuf() == nullptr)
|
||||
{
|
||||
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
}
|
||||
return input_stream_adapter(stream);
|
||||
}
|
||||
@@ -827,7 +827,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b)
|
||||
{
|
||||
if (b == nullptr)
|
||||
{
|
||||
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
}
|
||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||
const auto* ptr = reinterpret_cast<const char*>(b);
|
||||
|
||||
@@ -178,6 +178,27 @@ template<typename ArrayType>
|
||||
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
||||
{}
|
||||
|
||||
/*!
|
||||
@brief reports an object or array whose announced size exceeds max_size()
|
||||
|
||||
Shared by json_sax_dom_parser and json_sax_dom_callback_parser.
|
||||
|
||||
@param[in] sax the SAX parser to report the error to
|
||||
@param[in] len the number of elements announced by the input, or unknown_size()
|
||||
@param[in] kind "object" or "array"
|
||||
@param[in] ref the object or array that was just created
|
||||
@return whether parsing should continue (false after reporting out_of_range.408)
|
||||
*/
|
||||
template<typename SAX, typename BasicJsonType>
|
||||
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()))
|
||||
{
|
||||
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
/*!
|
||||
@brief set the diagnostic positions of a value the DOM SAX parsers just stored
|
||||
@@ -187,6 +208,35 @@ befriends this struct, as the position members are private.
|
||||
*/
|
||||
struct diagnostic_positions
|
||||
{
|
||||
/*!
|
||||
@param[in,out] v the object or array whose opening brace or bracket was just read
|
||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||
*/
|
||||
template<typename BasicJsonType, typename LexerType>
|
||||
static void set_container_start(BasicJsonType& v, LexerType* lexer)
|
||||
{
|
||||
if (lexer)
|
||||
{
|
||||
// Lexer has read the first character of the container, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
v.start_position = lexer->get_position() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@param[in,out] v the object or array whose closing brace or bracket was just read
|
||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||
*/
|
||||
template<typename BasicJsonType, typename LexerType>
|
||||
static void set_container_end(BasicJsonType& v, LexerType* lexer)
|
||||
{
|
||||
if (lexer)
|
||||
{
|
||||
// Lexer's position is past the closing brace or bracket, so set that as the end position.
|
||||
v.end_position = lexer->get_position();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@param[in,out] v the value that was just parsed
|
||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||
@@ -354,22 +404,11 @@ class json_sax_dom_parser
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the object here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer has read the first character of the object, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
|
||||
}
|
||||
|
||||
return true;
|
||||
return check_container_size(*this, len, "object", ref_stack.back());
|
||||
}
|
||||
|
||||
bool key(string_t& val)
|
||||
@@ -388,11 +427,7 @@ class json_sax_dom_parser
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing brace, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -405,17 +440,13 @@ class json_sax_dom_parser
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the array here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
@@ -432,11 +463,7 @@ class json_sax_dom_parser
|
||||
JSON_ASSERT(ref_stack.back()->is_array());
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing bracket, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -616,21 +643,11 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the object here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer has read the first character of the object, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
// check object limit
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
|
||||
}
|
||||
return check_container_size(*this, len, "object", ref_stack.back());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -700,11 +717,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing brace, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -715,13 +728,7 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
JSON_ASSERT(!container_key_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
const string_t object_key = std::move(container_key_stack.back());
|
||||
container_key_stack.pop_back();
|
||||
const string_t object_key = pop_container();
|
||||
|
||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
||||
{
|
||||
@@ -747,20 +754,13 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the array here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer has read the first character of the array, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
// check array limit
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
@@ -784,11 +784,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing bracket, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -814,13 +810,7 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
JSON_ASSERT(!container_key_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
const string_t object_key = std::move(container_key_stack.back());
|
||||
container_key_stack.pop_back();
|
||||
const string_t object_key = pop_container();
|
||||
|
||||
// remove discarded value
|
||||
if (!ref_stack.empty() && ref_stack.back())
|
||||
@@ -907,6 +897,23 @@ class json_sax_dom_callback_parser
|
||||
return string_t{};
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief leave the object or array that end_object()/end_array() just closed
|
||||
@return the key the container is stored under in its parent (see
|
||||
container_key_stack)
|
||||
*/
|
||||
string_t pop_container()
|
||||
{
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
JSON_ASSERT(!container_key_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
string_t object_key = std::move(container_key_stack.back());
|
||||
container_key_stack.pop_back();
|
||||
return object_key;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief remove the discarded value the callback rejected from its parent,
|
||||
unless it is a duplicate key's slot with a stashed previous value, in
|
||||
|
||||
@@ -189,7 +189,7 @@ class parser
|
||||
if (last_token != token_type::end_of_input && get_token() != token_type::end_of_input)
|
||||
{
|
||||
// the value is complete, so there is nothing to recover
|
||||
static_cast<void>(report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr),
|
||||
static_cast<void>(report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr),
|
||||
std::integral_constant<bool, AllowRecovery> {}));
|
||||
return false;
|
||||
}
|
||||
@@ -229,10 +229,7 @@ class parser
|
||||
// in strict mode, input must be completely read
|
||||
if (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"), nullptr));
|
||||
syntax_error(sdp, exception_message(token_type::end_of_input, "value"));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -424,7 +421,7 @@ class parser
|
||||
case token_type::parse_error:
|
||||
{
|
||||
// using "uninitialized" to avoid an "expected" message
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr), allow_recovery))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -457,12 +454,12 @@ class parser
|
||||
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
|
||||
{
|
||||
// there is nothing to recover
|
||||
static_cast<void>(report_error(sax, parse_error::create(101, m_lexer.get_position(),
|
||||
static_cast<void>(report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(),
|
||||
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr), allow_recovery));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr), allow_recovery))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -490,7 +487,7 @@ class parser
|
||||
case token_type::literal_or_value:
|
||||
default: // the last token was unexpected
|
||||
{
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr), allow_recovery))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -569,7 +566,7 @@ class parser
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr), allow_recovery))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -655,7 +652,7 @@ class parser
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr), allow_recovery))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -759,7 +756,7 @@ class parser
|
||||
template<typename SAX>
|
||||
bool overflow_error(SAX* sax, const number_float_t value, std::true_type allow_recovery)
|
||||
{
|
||||
if (!report_error(sax, out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr), allow_recovery))
|
||||
if (!report_error(sax, out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr), allow_recovery))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -771,7 +768,7 @@ class parser
|
||||
JSON_INTERNAL_ALWAYS_INLINE
|
||||
std::false_type overflow_error(SAX* sax, const number_float_t /*value*/, std::false_type allow_recovery)
|
||||
{
|
||||
return report_error(sax, out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr), allow_recovery);
|
||||
return report_error(sax, out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr), allow_recovery);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -786,7 +783,7 @@ class parser
|
||||
JSON_INTERNAL_ALWAYS_INLINE
|
||||
std::false_type key_error(SAX* sax, std::false_type allow_recovery, const bool key_read)
|
||||
{
|
||||
return report_error(sax, parse_error::create(101, m_lexer.get_position(), key_read
|
||||
return report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), key_read
|
||||
? exception_message(token_type::name_separator, "object separator")
|
||||
: exception_message(token_type::value_string, "object key"), nullptr), allow_recovery);
|
||||
}
|
||||
@@ -803,14 +800,14 @@ class parser
|
||||
{
|
||||
if (!key_read)
|
||||
{
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr), allow_recovery))
|
||||
{
|
||||
return next_step::stop;
|
||||
}
|
||||
return recover_key(sax);
|
||||
}
|
||||
|
||||
if (!report_error(sax, parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr), allow_recovery))
|
||||
if (!report_error(sax, parse_error::create(exception_id::syntax_error, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr), allow_recovery))
|
||||
{
|
||||
return next_step::stop;
|
||||
}
|
||||
@@ -1208,6 +1205,21 @@ class parser
|
||||
return (last_token = m_lexer.scan_expecting(expected_type)) == expected_type;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reports a syntax error at the current token (parse_error.101)
|
||||
@param[in] sax the SAX parser to report the error to
|
||||
@param[in] message the error message
|
||||
@return the result of the SAX parser's parse_error()
|
||||
*/
|
||||
template<typename SAX>
|
||||
bool syntax_error(SAX& sax, const std::string& message)
|
||||
{
|
||||
// MSVC 2015 reports C4100 (unreferenced parameter) when SAX::parse_error is static
|
||||
static_cast<void>(sax);
|
||||
return sax.parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
|
||||
parse_error::create(exception_id::syntax_error, m_lexer.get_position(), message, nullptr));
|
||||
}
|
||||
|
||||
std::string exception_message(const token_type expected, const std::string& context)
|
||||
{
|
||||
std::string error_msg = "syntax error ";
|
||||
|
||||
Reference in new issue
Block a user