1// __ _____ _____ _____ 2// __| | __| | | | JSON for Modern C++ 3// | | |__ | | | | | | version 3.11.2 4// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5// 6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 7// SPDX-License-Identifier: MIT 8 9#pragma once 10 11#include <cstddef> // nullptr_t 12#include <exception> // exception 13#include <stdexcept> // runtime_error 14#include <string> // to_string 15#include <vector> // vector 16 17#include <nlohmann/detail/value_t.hpp> 18#include <nlohmann/detail/string_escape.hpp> 19#include <nlohmann/detail/input/position_t.hpp> 20#include <nlohmann/detail/macro_scope.hpp> 21#include <nlohmann/detail/meta/cpp_future.hpp> 22#include <nlohmann/detail/meta/type_traits.hpp> 23#include <nlohmann/detail/string_concat.hpp> 24 25 26NLOHMANN_JSON_NAMESPACE_BEGIN 27namespace detail 28{ 29 30//////////////// 31// exceptions // 32//////////////// 33 34/// @brief general exception of the @ref basic_json class 35/// @sa https://json.nlohmann.me/api/basic_json/exception/ 36class exception : public std::exception 37{ 38 public: 39 /// returns the explanatory string 40 const char* what() const noexcept override 41 { 42 return m.what(); 43 } 44 45 /// the id of the exception 46 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) 47 48 protected: 49 JSON_HEDLEY_NON_NULL(3) 50 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) 51 52 static std::string name(const std::string& ename, int id_) 53 { 54 return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); 55 } 56 57 static std::string diagnostics(std::nullptr_t /*leaf_element*/) 58 { 59 return ""; 60 } 61 62 template<typename BasicJsonType> 63 static std::string diagnostics(const BasicJsonType* leaf_element) 64 { 65#if JSON_DIAGNOSTICS 66 std::vector<std::string> tokens; 67 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) 68 { 69 switch (current->m_parent->type()) 70 { 71 case value_t::array: 72 { 73 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) 74 { 75 if (¤t->m_parent->m_value.array->operator[](i) == current) 76 { 77 tokens.emplace_back(std::to_string(i)); 78 break; 79 } 80 } 81 break; 82 } 83 84 case value_t::object: 85 { 86 for (const auto& element : *current->m_parent->m_value.object) 87 { 88 if (&element.second == current) 89 { 90 tokens.emplace_back(element.first.c_str()); 91 break; 92 } 93 } 94 break; 95 } 96 97 case value_t::null: // LCOV_EXCL_LINE 98 case value_t::string: // LCOV_EXCL_LINE 99 case value_t::boolean: // LCOV_EXCL_LINE 100 case value_t::number_integer: // LCOV_EXCL_LINE 101 case value_t::number_unsigned: // LCOV_EXCL_LINE 102 case value_t::number_float: // LCOV_EXCL_LINE 103 case value_t::binary: // LCOV_EXCL_LINE 104 case value_t::discarded: // LCOV_EXCL_LINE 105 default: // LCOV_EXCL_LINE 106 break; // LCOV_EXCL_LINE 107 } 108 } 109 110 if (tokens.empty()) 111 { 112 return ""; 113 } 114 115 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, 116 [](const std::string & a, const std::string & b) 117 { 118 return concat(a, '/', detail::escape(b)); 119 }); 120 return concat('(', str, ") "); 121#else 122 static_cast<void>(leaf_element); 123 return ""; 124#endif 125 } 126 127 private: 128 /// an exception object as storage for error messages 129 std::runtime_error m; 130}; 131 132/// @brief exception indicating a parse error 133/// @sa https://json.nlohmann.me/api/basic_json/parse_error/ 134class parse_error : public exception 135{ 136 public: 137 /*! 138 @brief create a parse error exception 139 @param[in] id_ the id of the exception 140 @param[in] pos the position where the error occurred (or with 141 chars_read_total=0 if the position cannot be 142 determined) 143 @param[in] what_arg the explanatory string 144 @return parse_error object 145 */ 146 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 147 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) 148 { 149 std::string w = concat(exception::name("parse_error", id_), "parse error", 150 position_string(pos), ": ", exception::diagnostics(context), what_arg); 151 return {id_, pos.chars_read_total, w.c_str()}; 152 } 153 154 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 155 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) 156 { 157 std::string w = concat(exception::name("parse_error", id_), "parse error", 158 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), 159 ": ", exception::diagnostics(context), what_arg); 160 return {id_, byte_, w.c_str()}; 161 } 162 163 /*! 164 @brief byte index of the parse error 165 166 The byte index of the last read character in the input file. 167 168 @note For an input with n bytes, 1 is the index of the first character and 169 n+1 is the index of the terminating null byte or the end of file. 170 This also holds true when reading a byte vector (CBOR or MessagePack). 171 */ 172 const std::size_t byte; 173 174 private: 175 parse_error(int id_, std::size_t byte_, const char* what_arg) 176 : exception(id_, what_arg), byte(byte_) {} 177 178 static std::string position_string(const position_t& pos) 179 { 180 return concat(" at line ", std::to_string(pos.lines_read + 1), 181 ", column ", std::to_string(pos.chars_read_current_line)); 182 } 183}; 184 185/// @brief exception indicating errors with iterators 186/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ 187class invalid_iterator : public exception 188{ 189 public: 190 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 191 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) 192 { 193 std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); 194 return {id_, w.c_str()}; 195 } 196 197 private: 198 JSON_HEDLEY_NON_NULL(3) 199 invalid_iterator(int id_, const char* what_arg) 200 : exception(id_, what_arg) {} 201}; 202 203/// @brief exception indicating executing a member function with a wrong type 204/// @sa https://json.nlohmann.me/api/basic_json/type_error/ 205class type_error : public exception 206{ 207 public: 208 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 209 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) 210 { 211 std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); 212 return {id_, w.c_str()}; 213 } 214 215 private: 216 JSON_HEDLEY_NON_NULL(3) 217 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 218}; 219 220/// @brief exception indicating access out of the defined range 221/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ 222class out_of_range : public exception 223{ 224 public: 225 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 226 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) 227 { 228 std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); 229 return {id_, w.c_str()}; 230 } 231 232 private: 233 JSON_HEDLEY_NON_NULL(3) 234 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} 235}; 236 237/// @brief exception indicating other library errors 238/// @sa https://json.nlohmann.me/api/basic_json/other_error/ 239class other_error : public exception 240{ 241 public: 242 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 243 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) 244 { 245 std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); 246 return {id_, w.c_str()}; 247 } 248 249 private: 250 JSON_HEDLEY_NON_NULL(3) 251 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 252}; 253 254} // namespace detail 255NLOHMANN_JSON_NAMESPACE_END 256