| // __ _____ _____ _____ | |
| // __| | __| | | | JSON for Modern C++ | |
| // | | |__ | | | | | | version 3.12.0 | |
| // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
| // | |
| // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me> | |
| // SPDX-License-Identifier: MIT | |
| #pragma once | |
| #include <algorithm> // min | |
| #include <cstddef> // size_t | |
| #include <string> // string | |
| #include <nlohmann/json.hpp> | |
| #include <nlohmann/detail/view/builder.hpp> | |
| #include <nlohmann/detail/view/macro_scope.hpp> | |
| NLOHMANN_JSON_NAMESPACE_BEGIN | |
| namespace detail | |
| { | |
| namespace view | |
| { | |
| // Exceptions are thrown out of line, so that the accessors that may throw stay | |
| // small enough to be inlined. | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE inline void throw_type_error(exception_id id, const char* prefix, const char* type) | |
| { | |
| NLOHMANN_VIEW_THROW(type_error::create(id, concat(prefix, type), nullptr)); | |
| } | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE inline void throw_type_error(exception_id id, const std::string& msg) | |
| { | |
| NLOHMANN_VIEW_THROW(type_error::create(id, msg, nullptr)); | |
| } | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE inline void throw_out_of_range(exception_id id, const std::string& msg) | |
| { | |
| NLOHMANN_VIEW_THROW(out_of_range::create(id, msg, nullptr)); | |
| } | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE inline void throw_invalid_iterator(exception_id id, const char* msg) | |
| { | |
| NLOHMANN_VIEW_THROW(invalid_iterator::create(id, msg, nullptr)); | |
| } | |
| /// a parse error without a position (as those of json_pointer) | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE inline void throw_parse_error(exception_id id, const std::string& msg) | |
| { | |
| NLOHMANN_VIEW_THROW(parse_error::create(id, 0, msg, nullptr)); | |
| } | |
| /// out_of_range.401: the array index @a idx is not below the size | |
| template<typename Index> | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE void throw_array_index_out_of_range(const Index idx) | |
| { | |
| throw_out_of_range(exception_id::array_index_out_of_range, concat("array index ", std::to_string(idx), " is out of range")); | |
| } | |
| /// out_of_range.402: the JSON Pointer token '-' of an array of @a size elements | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE inline void throw_array_index_past_end(std::size_t size) | |
| { | |
| throw_out_of_range(exception_id::pointer_past_the_end_index, concat("array index '-' (", std::to_string(size), ") is out of range")); | |
| } | |
| /// out_of_range.403: the object has no member @a key | |
| template<typename Key> | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE void throw_key_not_found(const Key& key) | |
| { | |
| throw_out_of_range(exception_id::key_not_found, concat("key '", key, "' not found")); | |
| } | |
| /// SAX handler of the error replay: accepts every event without storing it, | |
| /// and throws the exception the parser reports | |
| template<typename BasicJsonType> | |
| struct throwing_sax | |
| { | |
| using number_integer_t = typename BasicJsonType::number_integer_t; | |
| using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
| using number_float_t = typename BasicJsonType::number_float_t; | |
| using string_t = typename BasicJsonType::string_t; | |
| using binary_t = typename BasicJsonType::binary_t; | |
| bool null() | |
| { | |
| return true; | |
| } | |
| bool boolean(bool /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool number_integer(number_integer_t /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool number_unsigned(number_unsigned_t /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool string(string_t& /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool binary(binary_t& /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool start_object(std::size_t /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool key(string_t& /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool end_object() | |
| { | |
| return true; | |
| } | |
| bool start_array(std::size_t /*unused*/) | |
| { | |
| return true; | |
| } | |
| bool end_array() | |
| { | |
| return true; | |
| } | |
| /// (a template, as in json_sax_dom_parser: the parser passes the concrete | |
| /// exception type, which is thrown as is) | |
| template<class Exception> | |
| [[noreturn]] bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex) | |
| { | |
| NLOHMANN_VIEW_THROW(ex); | |
| } | |
| }; | |
| /*! | |
| @brief throw the exception BasicJsonType::parse would throw for this input | |
| The view accepts exactly the inputs parse() accepts, so on a failure the | |
| library parser is run on the same bytes: it throws the exception parse() would | |
| throw, with the same message, position, and "last read" token. The replay | |
| uses a SAX handler that stores nothing, so it only lexes and parses up to the | |
| error, without building values. The error path is cold, so this costs nothing | |
| on valid input. Should parse() accept the input nevertheless (a bug), the | |
| view's own failure is reported. | |
| */ | |
| template<typename BasicJsonType> | |
| [[noreturn]] NLOHMANN_VIEW_NOINLINE void throw_parse_failure(const parse_failure& f, const char* src, std::size_t size, | |
| bool ignore_comments, bool ignore_trailing_commas) | |
| { | |
| if (f.code == error_code::input_too_large) | |
| { | |
| // (the limit is detail::view::max_input_size(): 4 GiB minus 16 bytes) | |
| NLOHMANN_VIEW_THROW(out_of_range::create(exception_id::document_too_large, "input of 4294967280 bytes or more is not supported by json_document", nullptr)); | |
| } | |
| throwing_sax<BasicJsonType> sax; | |
| const bool accepted = BasicJsonType::sax_parse(src, src + size, &sax, input_format_t::json, true, ignore_comments, ignore_trailing_commas); | |
| // LCOV_EXCL_START (only if parse() accepts what the view rejects: a bug) | |
| static_cast<void>(accepted); | |
| position_t pos; | |
| const std::size_t off = (std::min)(f.offset, size); | |
| pos.chars_read_total = off + 1; | |
| std::size_t line_start = 0; | |
| for (std::size_t i = 0; i < off; ++i) | |
| { | |
| if (src[i] == '\n') | |
| { | |
| ++pos.lines_read; | |
| line_start = i + 1; | |
| } | |
| } | |
| pos.chars_read_current_line = off + 1 - line_start; | |
| NLOHMANN_VIEW_THROW(parse_error::create(exception_id::syntax_error, pos, "syntax error while parsing value", nullptr)); | |
| // LCOV_EXCL_STOP | |
| } | |
| } // namespace view | |
| } // namespace detail | |
| NLOHMANN_JSON_NAMESPACE_END |