// __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once #include // nullptr_t #include // exception #include // runtime_error #include // to_string #include // vector #include #include #include #include #include #include #include NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { //////////////// // exceptions // //////////////// /// @brief general exception of the @ref basic_json class /// @sa https://json.nlohmann.me/api/basic_json/exception/ class exception : public std::exception { public: /// returns the explanatory string const char* what() const noexcept override { return m.what(); } /// the id of the exception const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) protected: JSON_HEDLEY_NON_NULL(3) exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) static std::string name(const std::string& ename, int id_) { return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); } static std::string diagnostics(std::nullptr_t /*leaf_element*/) { return ""; } template static std::string diagnostics(const BasicJsonType* leaf_element) { #if JSON_DIAGNOSTICS std::vector tokens; for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) { switch (current->m_parent->type()) { case value_t::array: { for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) { if (¤t->m_parent->m_value.array->operator[](i) == current) { tokens.emplace_back(std::to_string(i)); break; } } break; } case value_t::object: { for (const auto& element : *current->m_parent->m_value.object) { if (&element.second == current) { tokens.emplace_back(element.first.c_str()); break; } } break; } case value_t::null: // LCOV_EXCL_LINE case value_t::string: // LCOV_EXCL_LINE case value_t::boolean: // LCOV_EXCL_LINE case value_t::number_integer: // LCOV_EXCL_LINE case value_t::number_unsigned: // LCOV_EXCL_LINE case value_t::number_float: // LCOV_EXCL_LINE case value_t::binary: // LCOV_EXCL_LINE case value_t::discarded: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE break; // LCOV_EXCL_LINE } } if (tokens.empty()) { return ""; } auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, [](const std::string & a, const std::string & b) { return concat(a, '/', detail::escape(b)); }); return concat('(', str, ") "); #else static_cast(leaf_element); return ""; #endif } private: /// an exception object as storage for error messages std::runtime_error m; }; /// @brief exception indicating a parse error /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ class parse_error : public exception { public: /*! @brief create a parse error exception @param[in] id_ the id of the exception @param[in] pos the position where the error occurred (or with chars_read_total=0 if the position cannot be determined) @param[in] what_arg the explanatory string @return parse_error object */ template::value, int> = 0> static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) { std::string w = concat(exception::name("parse_error", id_), "parse error", position_string(pos), ": ", exception::diagnostics(context), what_arg); return {id_, pos.chars_read_total, w.c_str()}; } template::value, int> = 0> static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) { std::string w = concat(exception::name("parse_error", id_), "parse error", (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), ": ", exception::diagnostics(context), what_arg); return {id_, byte_, w.c_str()}; } /*! @brief byte index of the parse error The byte index of the last read character in the input file. @note For an input with n bytes, 1 is the index of the first character and n+1 is the index of the terminating null byte or the end of file. This also holds true when reading a byte vector (CBOR or MessagePack). */ const std::size_t byte; private: parse_error(int id_, std::size_t byte_, const char* what_arg) : exception(id_, what_arg), byte(byte_) {} static std::string position_string(const position_t& pos) { return concat(" at line ", std::to_string(pos.lines_read + 1), ", column ", std::to_string(pos.chars_read_current_line)); } }; /// @brief exception indicating errors with iterators /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ class invalid_iterator : public exception { public: template::value, int> = 0> static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) { std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } private: JSON_HEDLEY_NON_NULL(3) invalid_iterator(int id_, const char* what_arg) : exception(id_, what_arg) {} }; /// @brief exception indicating executing a member function with a wrong type /// @sa https://json.nlohmann.me/api/basic_json/type_error/ class type_error : public exception { public: template::value, int> = 0> static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) { std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } private: JSON_HEDLEY_NON_NULL(3) type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} }; /// @brief exception indicating access out of the defined range /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ class out_of_range : public exception { public: template::value, int> = 0> static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) { std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } private: JSON_HEDLEY_NON_NULL(3) out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} }; /// @brief exception indicating other library errors /// @sa https://json.nlohmann.me/api/basic_json/other_error/ class other_error : public exception { public: template::value, int> = 0> static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) { std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } private: JSON_HEDLEY_NON_NULL(3) other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} }; } // namespace detail NLOHMANN_JSON_NAMESPACE_END