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