File indexing completed on 2025-03-13 09:15:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <cstddef> // nullptr_t
0012 #include <exception> // exception
0013 #include <stdexcept> // runtime_error
0014 #include <string> // to_string
0015 #include <vector> // vector
0016
0017 #include <nlohmann/detail/value_t.hpp>
0018 #include <nlohmann/detail/string_escape.hpp>
0019 #include <nlohmann/detail/input/position_t.hpp>
0020 #include <nlohmann/detail/macro_scope.hpp>
0021 #include <nlohmann/detail/meta/cpp_future.hpp>
0022 #include <nlohmann/detail/meta/type_traits.hpp>
0023 #include <nlohmann/detail/string_concat.hpp>
0024
0025
0026 NLOHMANN_JSON_NAMESPACE_BEGIN
0027 namespace detail
0028 {
0029
0030
0031
0032
0033
0034
0035
0036 class exception : public std::exception
0037 {
0038 public:
0039
0040 const char* what() const noexcept override
0041 {
0042 return m.what();
0043 }
0044
0045
0046 const int id;
0047
0048 protected:
0049 JSON_HEDLEY_NON_NULL(3)
0050 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
0051
0052 static std::string name(const std::string& ename, int id_)
0053 {
0054 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
0055 }
0056
0057 static std::string diagnostics(std::nullptr_t )
0058 {
0059 return "";
0060 }
0061
0062 template<typename BasicJsonType>
0063 static std::string diagnostics(const BasicJsonType* leaf_element)
0064 {
0065 #if JSON_DIAGNOSTICS
0066 std::vector<std::string> tokens;
0067 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
0068 {
0069 switch (current->m_parent->type())
0070 {
0071 case value_t::array:
0072 {
0073 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
0074 {
0075 if (¤t->m_parent->m_value.array->operator[](i) == current)
0076 {
0077 tokens.emplace_back(std::to_string(i));
0078 break;
0079 }
0080 }
0081 break;
0082 }
0083
0084 case value_t::object:
0085 {
0086 for (const auto& element : *current->m_parent->m_value.object)
0087 {
0088 if (&element.second == current)
0089 {
0090 tokens.emplace_back(element.first.c_str());
0091 break;
0092 }
0093 }
0094 break;
0095 }
0096
0097 case value_t::null:
0098 case value_t::string:
0099 case value_t::boolean:
0100 case value_t::number_integer:
0101 case value_t::number_unsigned:
0102 case value_t::number_float:
0103 case value_t::binary:
0104 case value_t::discarded:
0105 default:
0106 break;
0107 }
0108 }
0109
0110 if (tokens.empty())
0111 {
0112 return "";
0113 }
0114
0115 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
0116 [](const std::string & a, const std::string & b)
0117 {
0118 return concat(a, '/', detail::escape(b));
0119 });
0120 return concat('(', str, ") ");
0121 #else
0122 static_cast<void>(leaf_element);
0123 return "";
0124 #endif
0125 }
0126
0127 private:
0128
0129 std::runtime_error m;
0130 };
0131
0132
0133
0134 class parse_error : public exception
0135 {
0136 public:
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
0147 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
0148 {
0149 std::string w = concat(exception::name("parse_error", id_), "parse error",
0150 position_string(pos), ": ", exception::diagnostics(context), what_arg);
0151 return {id_, pos.chars_read_total, w.c_str()};
0152 }
0153
0154 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
0155 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
0156 {
0157 std::string w = concat(exception::name("parse_error", id_), "parse error",
0158 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
0159 ": ", exception::diagnostics(context), what_arg);
0160 return {id_, byte_, w.c_str()};
0161 }
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 const std::size_t byte;
0173
0174 private:
0175 parse_error(int id_, std::size_t byte_, const char* what_arg)
0176 : exception(id_, what_arg), byte(byte_) {}
0177
0178 static std::string position_string(const position_t& pos)
0179 {
0180 return concat(" at line ", std::to_string(pos.lines_read + 1),
0181 ", column ", std::to_string(pos.chars_read_current_line));
0182 }
0183 };
0184
0185
0186
0187 class invalid_iterator : public exception
0188 {
0189 public:
0190 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
0191 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
0192 {
0193 std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
0194 return {id_, w.c_str()};
0195 }
0196
0197 private:
0198 JSON_HEDLEY_NON_NULL(3)
0199 invalid_iterator(int id_, const char* what_arg)
0200 : exception(id_, what_arg) {}
0201 };
0202
0203
0204
0205 class type_error : public exception
0206 {
0207 public:
0208 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
0209 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
0210 {
0211 std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
0212 return {id_, w.c_str()};
0213 }
0214
0215 private:
0216 JSON_HEDLEY_NON_NULL(3)
0217 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
0218 };
0219
0220
0221
0222 class out_of_range : public exception
0223 {
0224 public:
0225 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
0226 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
0227 {
0228 std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
0229 return {id_, w.c_str()};
0230 }
0231
0232 private:
0233 JSON_HEDLEY_NON_NULL(3)
0234 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
0235 };
0236
0237
0238
0239 class other_error : public exception
0240 {
0241 public:
0242 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
0243 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
0244 {
0245 std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
0246 return {id_, w.c_str()};
0247 }
0248
0249 private:
0250 JSON_HEDLEY_NON_NULL(3)
0251 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
0252 };
0253
0254 }
0255 NLOHMANN_JSON_NAMESPACE_END