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