mirror of https://github.com/PurpleI2P/i2pd.git
I2P: End-to-End encrypted and anonymous Internet
https://i2pd.website/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
7.8 KiB
236 lines
7.8 KiB
#pragma once |
|
|
|
#include <exception> // exception |
|
#include <stdexcept> // runtime_error |
|
#include <string> // to_string |
|
#include <vector> // vector |
|
|
|
#include <nlohmann/detail/value_t.hpp> |
|
#include <nlohmann/detail/string_escape.hpp> |
|
#include <nlohmann/detail/input/position_t.hpp> |
|
#include <nlohmann/detail/macro_scope.hpp> |
|
|
|
namespace nlohmann |
|
{ |
|
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 "[json.exception." + ename + "." + std::to_string(id_) + "] "; |
|
} |
|
|
|
template<typename BasicJsonType> |
|
static std::string diagnostics(const BasicJsonType& leaf_element) |
|
{ |
|
#if JSON_DIAGNOSTICS |
|
std::vector<std::string> tokens; |
|
for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) |
|
{ |
|
switch (current->m_parent->type()) |
|
{ |
|
case value_t::array: |
|
{ |
|
for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) |
|
{ |
|
if (¤t->m_parent->m_value.array->operator[](i) == current) |
|
{ |
|
tokens.emplace_back(std::to_string(i)); |
|
break; |
|
} |
|
} |
|
break; |
|
} |
|
|
|
case value_t::object: |
|
{ |
|
for (const auto& element : *current->m_parent->m_value.object) |
|
{ |
|
if (&element.second == current) |
|
{ |
|
tokens.emplace_back(element.first.c_str()); |
|
break; |
|
} |
|
} |
|
break; |
|
} |
|
|
|
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 ""; |
|
} |
|
|
|
return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, |
|
[](const std::string & a, const std::string & b) |
|
{ |
|
return a + "/" + detail::escape(b); |
|
}) + ") "; |
|
#else |
|
static_cast<void>(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<typename BasicJsonType> |
|
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) |
|
{ |
|
std::string w = exception::name("parse_error", id_) + "parse error" + |
|
position_string(pos) + ": " + exception::diagnostics(context) + what_arg; |
|
return {id_, pos.chars_read_total, w.c_str()}; |
|
} |
|
|
|
template<typename BasicJsonType> |
|
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) |
|
{ |
|
std::string w = exception::name("parse_error", id_) + "parse error" + |
|
(byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + |
|
": " + 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 " 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<typename BasicJsonType> |
|
static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) |
|
{ |
|
std::string w = 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<typename BasicJsonType> |
|
static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) |
|
{ |
|
std::string w = 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<typename BasicJsonType> |
|
static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) |
|
{ |
|
std::string w = exception::name("out_of_range", id_) + 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<typename BasicJsonType> |
|
static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) |
|
{ |
|
std::string w = 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 |
|
} // namespace nlohmann
|
|
|