/src/jsoncons/include/jsoncons/json_exception.hpp
Line | Count | Source |
1 | | // Copyright 2013-2025 Daniel Parker |
2 | | // Distributed under the Boost license, Version 1.0. |
3 | | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
4 | | |
5 | | // See https://github.com/danielaparker/jsoncons for latest version |
6 | | |
7 | | #ifndef JSONCONS_JSON_EXCEPTION_HPP |
8 | | #define JSONCONS_JSON_EXCEPTION_HPP |
9 | | |
10 | | #include <cstddef> |
11 | | #include <exception> |
12 | | #include <stdexcept> |
13 | | #include <string> // std::string |
14 | | #include <system_error> // std::error_code |
15 | | |
16 | | #include <jsoncons/config/compiler_support.hpp> |
17 | | #include <jsoncons/utility/more_type_traits.hpp> |
18 | | #include <jsoncons/utility/unicode_traits.hpp> // unicode_traits::convert |
19 | | |
20 | | namespace jsoncons { |
21 | | |
22 | | // json_exception |
23 | | |
24 | | class json_exception |
25 | | { |
26 | | public: |
27 | 337 | virtual ~json_exception() = default; |
28 | | virtual const char* what() const noexcept = 0; |
29 | | }; |
30 | | |
31 | | // json_runtime_error |
32 | | |
33 | | template <typename Base,typename Enable = void> |
34 | | class json_runtime_error |
35 | | { |
36 | | }; |
37 | | |
38 | | template <typename Base> |
39 | | class json_runtime_error<Base, |
40 | | typename std::enable_if<std::is_convertible<Base*,std::exception*>::value && |
41 | | ext_traits::is_constructible_from_string<Base>::value>::type> |
42 | | : public Base, public virtual json_exception |
43 | | { |
44 | | public: |
45 | | json_runtime_error(const std::string& s) noexcept |
46 | 0 | : Base(s) |
47 | 0 | { |
48 | 0 | } |
49 | | ~json_runtime_error() noexcept |
50 | 0 | { |
51 | 0 | } |
52 | | const char* what() const noexcept override |
53 | 0 | { |
54 | 0 | return Base::what(); |
55 | 0 | } |
56 | | }; |
57 | | |
58 | | class bad_cast : public std::runtime_error |
59 | | { |
60 | | using std::runtime_error::runtime_error; |
61 | | }; |
62 | | |
63 | | class key_not_found : public std::out_of_range, public virtual json_exception |
64 | | { |
65 | | std::string name_; |
66 | | mutable std::string what_; |
67 | | public: |
68 | | template <typename CharT> |
69 | | explicit key_not_found(const CharT* key, std::size_t length) noexcept |
70 | | : std::out_of_range("Key not found") |
71 | | { |
72 | | JSONCONS_TRY |
73 | | { |
74 | | unicode_traits::convert(key, length, name_, |
75 | | unicode_traits::conv_flags::strict); |
76 | | } |
77 | | JSONCONS_CATCH(...) |
78 | | { |
79 | | } |
80 | | } |
81 | | |
82 | | virtual ~key_not_found() noexcept |
83 | 0 | { |
84 | 0 | } |
85 | | |
86 | | const char* what() const noexcept override |
87 | 0 | { |
88 | 0 | if (what_.empty()) |
89 | 0 | { |
90 | 0 | JSONCONS_TRY |
91 | 0 | { |
92 | 0 | what_.append(std::out_of_range::what()); |
93 | 0 | what_.append(": '"); |
94 | 0 | what_.append(name_); |
95 | 0 | what_.append("'"); |
96 | 0 | return what_.c_str(); |
97 | 0 | } |
98 | 0 | JSONCONS_CATCH(...) |
99 | 0 | { |
100 | 0 | return std::out_of_range::what(); |
101 | 0 | } |
102 | 0 | } |
103 | 0 | else |
104 | 0 | { |
105 | 0 | return what_.c_str(); |
106 | 0 | } |
107 | 0 | } |
108 | | }; |
109 | | |
110 | | class not_an_object : public std::runtime_error, public virtual json_exception |
111 | | { |
112 | | std::string name_; |
113 | | mutable std::string what_; |
114 | | public: |
115 | | template <typename CharT> |
116 | | explicit not_an_object(const CharT* key, std::size_t length) noexcept |
117 | | : std::runtime_error("Attempting to access a member of a value that is not an object") |
118 | | { |
119 | | JSONCONS_TRY |
120 | | { |
121 | | unicode_traits::convert(key, length, name_, |
122 | | unicode_traits::conv_flags::strict); |
123 | | } |
124 | | JSONCONS_CATCH(...) |
125 | | { |
126 | | } |
127 | | } |
128 | | |
129 | | virtual ~not_an_object() noexcept |
130 | 0 | { |
131 | 0 | } |
132 | | const char* what() const noexcept override |
133 | 0 | { |
134 | 0 | if (what_.empty()) |
135 | 0 | { |
136 | 0 | JSONCONS_TRY |
137 | 0 | { |
138 | 0 | what_.append(std::runtime_error::what()); |
139 | 0 | what_.append(": '"); |
140 | 0 | what_.append(name_); |
141 | 0 | what_.append("'"); |
142 | 0 | return what_.c_str(); |
143 | 0 | } |
144 | 0 | JSONCONS_CATCH(...) |
145 | 0 | { |
146 | 0 | return std::runtime_error::what(); |
147 | 0 | } |
148 | 0 | } |
149 | 0 | else |
150 | 0 | { |
151 | 0 | return what_.c_str(); |
152 | 0 | } |
153 | 0 | } |
154 | | }; |
155 | | |
156 | | class ser_error : public std::exception, public virtual json_exception |
157 | | { |
158 | | std::string err_; |
159 | | std::error_code ec_; |
160 | | std::size_t line_{0}; |
161 | | std::size_t column_{0}; |
162 | | public: |
163 | | ser_error(std::error_code ec) |
164 | | : ec_(ec) |
165 | 0 | { |
166 | 0 | err_ = to_what_arg(ec); |
167 | 0 | } |
168 | | ser_error(std::error_code ec, const std::string& what_arg) |
169 | | : ec_(ec) |
170 | 0 | { |
171 | 0 | err_ = to_what_arg(ec, what_arg.c_str()); |
172 | 0 | } |
173 | | ser_error(std::error_code ec, const char* what_arg) |
174 | | : ec_(ec) |
175 | 0 | { |
176 | 0 | err_ = to_what_arg(ec, what_arg); |
177 | 0 | } |
178 | | ser_error(std::error_code ec, std::size_t position) |
179 | | : ec_(ec), column_(position) |
180 | 0 | { |
181 | 0 | err_ = to_what_arg(ec, "", 0, position); |
182 | 0 | } |
183 | | ser_error(std::error_code ec, const std::string& what_arg, std::size_t position) |
184 | | : ec_(ec), column_(position) |
185 | 0 | { |
186 | 0 | err_ = to_what_arg(ec, what_arg.c_str(), 0, position); |
187 | 0 | } |
188 | | ser_error(std::error_code ec, const char* what_arg, std::size_t position) |
189 | | : ec_(ec), column_(position) |
190 | 0 | { |
191 | 0 | err_ = to_what_arg(ec, what_arg, 0, position); |
192 | 0 | } |
193 | | ser_error(std::error_code ec, std::size_t line, std::size_t column) |
194 | 337 | : ec_(ec), line_(line), column_(column) |
195 | 337 | { |
196 | 337 | err_ = to_what_arg(ec, "", line, column); |
197 | 337 | } |
198 | | ser_error(std::error_code ec, const std::string& what_arg, std::size_t line, std::size_t column) |
199 | | : ec_(ec), line_(line), column_(column) |
200 | 0 | { |
201 | 0 | err_ = to_what_arg(ec, what_arg.c_str(), line, column); |
202 | 0 | } |
203 | | ser_error(std::error_code ec, const char* what_arg, std::size_t line, std::size_t column) |
204 | | : ec_(ec), line_(line), column_(column) |
205 | 0 | { |
206 | 0 | err_ = to_what_arg(ec, what_arg, line, column); |
207 | 0 | } |
208 | | ser_error(const ser_error& other) = default; |
209 | | |
210 | | ser_error& operator=(const ser_error& other) = default; |
211 | | |
212 | | const char* what() const noexcept final |
213 | 0 | { |
214 | 0 | return err_.c_str(); |
215 | 0 | } |
216 | | |
217 | | std::error_code code() const |
218 | 0 | { |
219 | 0 | return ec_; |
220 | 0 | } |
221 | | |
222 | | std::size_t line() const noexcept |
223 | 0 | { |
224 | 0 | return line_; |
225 | 0 | } |
226 | | |
227 | | std::size_t column() const noexcept |
228 | 0 | { |
229 | 0 | return column_; |
230 | 0 | } |
231 | | private: |
232 | | static std::string to_what_arg(std::error_code ec, const char* s="", std::size_t line=0, std::size_t column=0) |
233 | 337 | { |
234 | 337 | std::string what_arg(s); |
235 | 337 | if (!what_arg.empty()) |
236 | 0 | { |
237 | 0 | what_arg.append(": "); |
238 | 0 | } |
239 | 337 | what_arg.append(ec.message()); |
240 | 337 | if (line != 0 && column != 0) |
241 | 0 | { |
242 | 0 | what_arg.append(" at line "); |
243 | 0 | what_arg.append(std::to_string(line)); |
244 | 0 | what_arg.append(" and column "); |
245 | 0 | what_arg.append(std::to_string(column)); |
246 | 0 | } |
247 | 337 | else if (column != 0) |
248 | 337 | { |
249 | 337 | what_arg.append(" at position "); |
250 | 337 | what_arg.append(std::to_string(column)); |
251 | 337 | } |
252 | 337 | return what_arg; |
253 | 337 | } |
254 | | }; |
255 | | |
256 | | } // namespace jsoncons |
257 | | |
258 | | #endif // JSONCONS_JSON_EXCEPTION_HPP |