1 | #ifndef SIMDJSON_INLINE_ERROR_H |
2 | #define SIMDJSON_INLINE_ERROR_H |
3 | |
4 | #include <cstring> |
5 | #include <string> |
6 | #include <utility> |
7 | #include "simdjson/error.h" |
8 | |
9 | namespace simdjson { |
10 | namespace internal { |
11 | // We store the error code so we can validate the error message is associated with the right code |
12 | struct error_code_info { |
13 | error_code code; |
14 | const char* message; // do not use a fancy std::string where a simple C string will do (no alloc, no destructor) |
15 | }; |
16 | // These MUST match the codes in error_code. We check this constraint in basictests. |
17 | extern SIMDJSON_DLLIMPORTEXPORT const error_code_info error_codes[]; |
18 | } // namespace internal |
19 | |
20 | |
21 | inline const char *error_message(error_code error) noexcept { |
22 | // If you're using error_code, we're trusting you got it from the enum. |
23 | return internal::error_codes[int(error)].message; |
24 | } |
25 | |
26 | // deprecated function |
27 | #ifndef SIMDJSON_DISABLE_DEPRECATED_API |
28 | inline const std::string error_message(int error) noexcept { |
29 | if (error < 0 || error >= error_code::NUM_ERROR_CODES) { |
30 | return internal::error_codes[UNEXPECTED_ERROR].message; |
31 | } |
32 | return internal::error_codes[error].message; |
33 | } |
34 | #endif // SIMDJSON_DISABLE_DEPRECATED_API |
35 | |
36 | inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept { |
37 | return out << error_message(error); |
38 | } |
39 | |
40 | namespace internal { |
41 | |
42 | // |
43 | // internal::simdjson_result_base<T> inline implementation |
44 | // |
45 | |
46 | template<typename T> |
47 | simdjson_inline void simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept { |
48 | error = this->second; |
49 | if (!error) { |
50 | value = std::forward<simdjson_result_base<T>>(*this).first; |
51 | } |
52 | } |
53 | |
54 | template<typename T> |
55 | simdjson_warn_unused simdjson_inline error_code simdjson_result_base<T>::get(T &value) && noexcept { |
56 | error_code error; |
57 | std::forward<simdjson_result_base<T>>(*this).tie(value, error); |
58 | return error; |
59 | } |
60 | |
61 | template<typename T> |
62 | simdjson_inline error_code simdjson_result_base<T>::error() const noexcept { |
63 | return this->second; |
64 | } |
65 | |
66 | #if SIMDJSON_EXCEPTIONS |
67 | |
68 | template<typename T> |
69 | simdjson_inline T& simdjson_result_base<T>::value() & noexcept(false) { |
70 | if (error()) { throw simdjson_error(error()); } |
71 | return this->first; |
72 | } |
73 | |
74 | template<typename T> |
75 | simdjson_inline T&& simdjson_result_base<T>::value() && noexcept(false) { |
76 | return std::forward<simdjson_result_base<T>>(*this).take_value(); |
77 | } |
78 | |
79 | template<typename T> |
80 | simdjson_inline T&& simdjson_result_base<T>::take_value() && noexcept(false) { |
81 | if (error()) { throw simdjson_error(error()); } |
82 | return std::forward<T>(this->first); |
83 | } |
84 | |
85 | template<typename T> |
86 | simdjson_inline simdjson_result_base<T>::operator T&&() && noexcept(false) { |
87 | return std::forward<simdjson_result_base<T>>(*this).take_value(); |
88 | } |
89 | |
90 | #endif // SIMDJSON_EXCEPTIONS |
91 | |
92 | template<typename T> |
93 | simdjson_inline const T& simdjson_result_base<T>::value_unsafe() const& noexcept { |
94 | return this->first; |
95 | } |
96 | |
97 | template<typename T> |
98 | simdjson_inline T&& simdjson_result_base<T>::value_unsafe() && noexcept { |
99 | return std::forward<T>(this->first); |
100 | } |
101 | |
102 | template<typename T> |
103 | simdjson_inline simdjson_result_base<T>::simdjson_result_base(T &&value, error_code error) noexcept |
104 | : std::pair<T, error_code>(std::forward<T>(value), error) {} |
105 | template<typename T> |
106 | simdjson_inline simdjson_result_base<T>::simdjson_result_base(error_code error) noexcept |
107 | : simdjson_result_base(T{}, error) {} |
108 | template<typename T> |
109 | simdjson_inline simdjson_result_base<T>::simdjson_result_base(T &&value) noexcept |
110 | : simdjson_result_base(std::forward<T>(value), SUCCESS) {} |
111 | template<typename T> |
112 | simdjson_inline simdjson_result_base<T>::simdjson_result_base() noexcept |
113 | : simdjson_result_base(T{}, UNINITIALIZED) {} |
114 | |
115 | } // namespace internal |
116 | |
117 | /// |
118 | /// simdjson_result<T> inline implementation |
119 | /// |
120 | |
121 | template<typename T> |
122 | simdjson_inline void simdjson_result<T>::tie(T &value, error_code &error) && noexcept { |
123 | std::forward<internal::simdjson_result_base<T>>(*this).tie(value, error); |
124 | } |
125 | |
126 | template<typename T> |
127 | simdjson_warn_unused simdjson_inline error_code simdjson_result<T>::get(T &value) && noexcept { |
128 | return std::forward<internal::simdjson_result_base<T>>(*this).get(value); |
129 | } |
130 | |
131 | template<typename T> |
132 | simdjson_inline error_code simdjson_result<T>::error() const noexcept { |
133 | return internal::simdjson_result_base<T>::error(); |
134 | } |
135 | |
136 | #if SIMDJSON_EXCEPTIONS |
137 | |
138 | template<typename T> |
139 | simdjson_inline T& simdjson_result<T>::value() & noexcept(false) { |
140 | return internal::simdjson_result_base<T>::value(); |
141 | } |
142 | |
143 | template<typename T> |
144 | simdjson_inline T&& simdjson_result<T>::value() && noexcept(false) { |
145 | return std::forward<internal::simdjson_result_base<T>>(*this).value(); |
146 | } |
147 | |
148 | template<typename T> |
149 | simdjson_inline T&& simdjson_result<T>::take_value() && noexcept(false) { |
150 | return std::forward<internal::simdjson_result_base<T>>(*this).take_value(); |
151 | } |
152 | |
153 | template<typename T> |
154 | simdjson_inline simdjson_result<T>::operator T&&() && noexcept(false) { |
155 | return std::forward<internal::simdjson_result_base<T>>(*this).take_value(); |
156 | } |
157 | |
158 | #endif // SIMDJSON_EXCEPTIONS |
159 | |
160 | template<typename T> |
161 | simdjson_inline const T& simdjson_result<T>::value_unsafe() const& noexcept { |
162 | return internal::simdjson_result_base<T>::value_unsafe(); |
163 | } |
164 | |
165 | template<typename T> |
166 | simdjson_inline T&& simdjson_result<T>::value_unsafe() && noexcept { |
167 | return std::forward<internal::simdjson_result_base<T>>(*this).value_unsafe(); |
168 | } |
169 | |
170 | template<typename T> |
171 | simdjson_inline simdjson_result<T>::simdjson_result(T &&value, error_code error) noexcept |
172 | : internal::simdjson_result_base<T>(std::forward<T>(value), error) {} |
173 | template<typename T> |
174 | simdjson_inline simdjson_result<T>::simdjson_result(error_code error) noexcept |
175 | : internal::simdjson_result_base<T>(error) {} |
176 | template<typename T> |
177 | simdjson_inline simdjson_result<T>::simdjson_result(T &&value) noexcept |
178 | : internal::simdjson_result_base<T>(std::forward<T>(value)) {} |
179 | template<typename T> |
180 | simdjson_inline simdjson_result<T>::simdjson_result() noexcept |
181 | : internal::simdjson_result_base<T>() {} |
182 | |
183 | } // namespace simdjson |
184 | |
185 | #endif // SIMDJSON_INLINE_ERROR_H |
186 | |