Coverage Report

Created: 2023-06-07 06:07

/src/simdjson/include/simdjson/error.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef SIMDJSON_ERROR_H
2
#define SIMDJSON_ERROR_H
3
4
#include "simdjson/common_defs.h"
5
#include <string>
6
7
namespace simdjson {
8
9
/**
10
 * All possible errors returned by simdjson. These error codes are subject to change
11
 * and not all simdjson kernel returns the same error code given the same input: it is not
12
 * well defined which error a given input should produce.
13
 *
14
 * Only SUCCESS evaluates to false as a Boolean. All other error codes will evaluate
15
 * to true as a Boolean.
16
 */
17
enum error_code {
18
  SUCCESS = 0,                ///< No error
19
  CAPACITY,                   ///< This parser can't support a document that big
20
  MEMALLOC,                   ///< Error allocating memory, most likely out of memory
21
  TAPE_ERROR,                 ///< Something went wrong, this is a generic error
22
  DEPTH_ERROR,                ///< Your document exceeds the user-specified depth limitation
23
  STRING_ERROR,               ///< Problem while parsing a string
24
  T_ATOM_ERROR,               ///< Problem while parsing an atom starting with the letter 't'
25
  F_ATOM_ERROR,               ///< Problem while parsing an atom starting with the letter 'f'
26
  N_ATOM_ERROR,               ///< Problem while parsing an atom starting with the letter 'n'
27
  NUMBER_ERROR,               ///< Problem while parsing a number
28
  UTF8_ERROR,                 ///< the input is not valid UTF-8
29
  UNINITIALIZED,              ///< unknown error, or uninitialized document
30
  EMPTY,                      ///< no structural element found
31
  UNESCAPED_CHARS,            ///< found unescaped characters in a string.
32
  UNCLOSED_STRING,            ///< missing quote at the end
33
  UNSUPPORTED_ARCHITECTURE,   ///< unsupported architecture
34
  INCORRECT_TYPE,             ///< JSON element has a different type than user expected
35
  NUMBER_OUT_OF_RANGE,        ///< JSON number does not fit in 64 bits
36
  INDEX_OUT_OF_BOUNDS,        ///< JSON array index too large
37
  NO_SUCH_FIELD,              ///< JSON field not found in object
38
  IO_ERROR,                   ///< Error reading a file
39
  INVALID_JSON_POINTER,       ///< Invalid JSON pointer reference
40
  INVALID_URI_FRAGMENT,       ///< Invalid URI fragment
41
  UNEXPECTED_ERROR,           ///< indicative of a bug in simdjson
42
  PARSER_IN_USE,              ///< parser is already in use.
43
  OUT_OF_ORDER_ITERATION,     ///< tried to iterate an array or object out of order
44
  INSUFFICIENT_PADDING,       ///< The JSON doesn't have enough padding for simdjson to safely parse it.
45
  INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
46
  SCALAR_DOCUMENT_AS_VALUE,   ///< A scalar document is treated as a value.
47
  OUT_OF_BOUNDS,              ///< Attempted to access location outside of document.
48
  TRAILING_CONTENT,           ///< Unexpected trailing content in the JSON input
49
  NUM_ERROR_CODES
50
};
51
52
/**
53
 * Get the error message for the given error code.
54
 *
55
 *   dom::parser parser;
56
 *   dom::element doc;
57
 *   auto error = parser.parse("foo",3).get(doc);
58
 *   if (error) { printf("Error: %s\n", error_message(error)); }
59
 *
60
 * @return The error message.
61
 */
62
inline const char *error_message(error_code error) noexcept;
63
64
/**
65
 * Write the error message to the output stream
66
 */
67
inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept;
68
69
/**
70
 * Exception thrown when an exception-supporting simdjson method is called
71
 */
72
struct simdjson_error : public std::exception {
73
  /**
74
   * Create an exception from a simdjson error code.
75
   * @param error The error code
76
   */
77
0
  simdjson_error(error_code error) noexcept : _error{error} { }
78
  /** The error message */
79
0
  const char *what() const noexcept { return error_message(error()); }
80
  /** The error code */
81
0
  error_code error() const noexcept { return _error; }
82
private:
83
  /** The error code that was used */
84
  error_code _error;
85
};
86
87
namespace internal {
88
89
/**
90
 * The result of a simdjson operation that could fail.
91
 *
92
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
93
 *
94
 * This is a base class for implementations that want to add functions to the result type for
95
 * chaining.
96
 *
97
 * Override like:
98
 *
99
 *   struct simdjson_result<T> : public internal::simdjson_result_base<T> {
100
 *     simdjson_result() noexcept : internal::simdjson_result_base<T>() {}
101
 *     simdjson_result(error_code error) noexcept : internal::simdjson_result_base<T>(error) {}
102
 *     simdjson_result(T &&value) noexcept : internal::simdjson_result_base<T>(std::forward(value)) {}
103
 *     simdjson_result(T &&value, error_code error) noexcept : internal::simdjson_result_base<T>(value, error) {}
104
 *     // Your extra methods here
105
 *   }
106
 *
107
 * Then any method returning simdjson_result<T> will be chainable with your methods.
108
 */
109
template<typename T>
110
struct simdjson_result_base : protected std::pair<T, error_code> {
111
112
  /**
113
   * Create a new empty result with error = UNINITIALIZED.
114
   */
115
  simdjson_inline simdjson_result_base() noexcept;
116
117
  /**
118
   * Create a new error result.
119
   */
120
  simdjson_inline simdjson_result_base(error_code error) noexcept;
121
122
  /**
123
   * Create a new successful result.
124
   */
125
  simdjson_inline simdjson_result_base(T &&value) noexcept;
126
127
  /**
128
   * Create a new result with both things (use if you don't want to branch when creating the result).
129
   */
130
  simdjson_inline simdjson_result_base(T &&value, error_code error) noexcept;
131
132
  /**
133
   * Move the value and the error to the provided variables.
134
   *
135
   * @param value The variable to assign the value to. May not be set if there is an error.
136
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
137
   */
138
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
139
140
  /**
141
   * Move the value to the provided variable.
142
   *
143
   * @param value The variable to assign the value to. May not be set if there is an error.
144
   */
145
  simdjson_inline error_code get(T &value) && noexcept;
146
147
  /**
148
   * The error.
149
   */
150
  simdjson_inline error_code error() const noexcept;
151
152
#if SIMDJSON_EXCEPTIONS
153
154
  /**
155
   * Get the result value.
156
   *
157
   * @throw simdjson_error if there was an error.
158
   */
159
  simdjson_inline T& value() & noexcept(false);
160
161
  /**
162
   * Take the result value (move it).
163
   *
164
   * @throw simdjson_error if there was an error.
165
   */
166
  simdjson_inline T&& value() && noexcept(false);
167
168
  /**
169
   * Take the result value (move it).
170
   *
171
   * @throw simdjson_error if there was an error.
172
   */
173
  simdjson_inline T&& take_value() && noexcept(false);
174
175
  /**
176
   * Cast to the value (will throw on error).
177
   *
178
   * @throw simdjson_error if there was an error.
179
   */
180
  simdjson_inline operator T&&() && noexcept(false);
181
#endif // SIMDJSON_EXCEPTIONS
182
183
  /**
184
   * Get the result value. This function is safe if and only
185
   * the error() method returns a value that evaluates to false.
186
   */
187
  simdjson_inline const T& value_unsafe() const& noexcept;
188
189
  /**
190
   * Take the result value (move it). This function is safe if and only
191
   * the error() method returns a value that evaluates to false.
192
   */
193
  simdjson_inline T&& value_unsafe() && noexcept;
194
195
}; // struct simdjson_result_base
196
197
} // namespace internal
198
199
/**
200
 * The result of a simdjson operation that could fail.
201
 *
202
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
203
 */
204
template<typename T>
205
struct simdjson_result : public internal::simdjson_result_base<T> {
206
  /**
207
   * @private Create a new empty result with error = UNINITIALIZED.
208
   */
209
  simdjson_inline simdjson_result() noexcept;
210
  /**
211
   * @private Create a new error result.
212
   */
213
  simdjson_inline simdjson_result(T &&value) noexcept;
214
  /**
215
   * @private Create a new successful result.
216
   */
217
  simdjson_inline simdjson_result(error_code error_code) noexcept;
218
  /**
219
   * @private Create a new result with both things (use if you don't want to branch when creating the result).
220
   */
221
  simdjson_inline simdjson_result(T &&value, error_code error) noexcept;
222
223
  /**
224
   * Move the value and the error to the provided variables.
225
   *
226
   * @param value The variable to assign the value to. May not be set if there is an error.
227
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
228
   */
229
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
230
231
  /**
232
   * Move the value to the provided variable.
233
   *
234
   * @param value The variable to assign the value to. May not be set if there is an error.
235
   */
236
  simdjson_warn_unused simdjson_inline error_code get(T &value) && noexcept;
237
238
  /**
239
   * The error.
240
   */
241
  simdjson_inline error_code error() const noexcept;
242
243
#if SIMDJSON_EXCEPTIONS
244
245
  /**
246
   * Get the result value.
247
   *
248
   * @throw simdjson_error if there was an error.
249
   */
250
  simdjson_inline T& value() & noexcept(false);
251
252
  /**
253
   * Take the result value (move it).
254
   *
255
   * @throw simdjson_error if there was an error.
256
   */
257
  simdjson_inline T&& value() && noexcept(false);
258
259
  /**
260
   * Take the result value (move it).
261
   *
262
   * @throw simdjson_error if there was an error.
263
   */
264
  simdjson_inline T&& take_value() && noexcept(false);
265
266
  /**
267
   * Cast to the value (will throw on error).
268
   *
269
   * @throw simdjson_error if there was an error.
270
   */
271
  simdjson_inline operator T&&() && noexcept(false);
272
#endif // SIMDJSON_EXCEPTIONS
273
274
  /**
275
   * Get the result value. This function is safe if and only
276
   * the error() method returns a value that evaluates to false.
277
   */
278
  simdjson_inline const T& value_unsafe() const& noexcept;
279
280
  /**
281
   * Take the result value (move it). This function is safe if and only
282
   * the error() method returns a value that evaluates to false.
283
   */
284
  simdjson_inline T&& value_unsafe() && noexcept;
285
286
}; // struct simdjson_result
287
288
#if SIMDJSON_EXCEPTIONS
289
290
template<typename T>
291
inline std::ostream& operator<<(std::ostream& out, simdjson_result<T> value) { return out << value.value(); }
292
#endif // SIMDJSON_EXCEPTIONS
293
294
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
295
/**
296
 * @deprecated This is an alias and will be removed, use error_code instead
297
 */
298
using ErrorValues [[deprecated("This is an alias and will be removed, use error_code instead")]] = error_code;
299
300
/**
301
 * @deprecated Error codes should be stored and returned as `error_code`, use `error_message()` instead.
302
 */
303
[[deprecated("Error codes should be stored and returned as `error_code`, use `error_message()` instead.")]]
304
inline const std::string error_message(int error) noexcept;
305
#endif // SIMDJSON_DISABLE_DEPRECATED_API
306
} // namespace simdjson
307
308
#endif // SIMDJSON_ERROR_H