Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
12 | | notice, this list of conditions and the following disclaimer in the | | ||
13 | | documentation and/or other materials provided with the distribution. | | ||
14 | | | | ||
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | #include "gate/results.h" | ||
30 | #include "gate/exceptions.hpp" | ||
31 | #include "gate/platforms.h" | ||
32 | #include "gate/strings.hpp" | ||
33 | |||
34 | #include <stdlib.h> | ||
35 | #include <stdio.h> | ||
36 | |||
37 | #if __cplusplus >= 201103L | ||
38 | # include <exception> | ||
39 | #endif | ||
40 | |||
41 | namespace gate | ||
42 | { | ||
43 | |||
44 | 76 | Throwable::~Throwable() noexcept | |
45 | { | ||
46 | |||
47 | 76 | } | |
48 | |||
49 | |||
50 | 13 | Error::Error(result_t result, char const* source, int32_t errCode) noexcept | |
51 | { | ||
52 | 13 | gate_mem_clear(&this->info, sizeof(this->info)); | |
53 | 13 | this->info.result_code = result; | |
54 | 13 | this->info.error_code = errCode; | |
55 | 13 | this->info.source = source; | |
56 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
|
13 | if (this->info.error_code == 0) |
57 | { | ||
58 | 12 | this->info.error_code = gate_platform_get_last_error(); | |
59 | } | ||
60 | 13 | } | |
61 | |||
62 | 26 | Error::~Error() noexcept | |
63 | { | ||
64 | 26 | } | |
65 | |||
66 | 1 | result_t Error::getResult() const noexcept | |
67 | { | ||
68 | 1 | return this->info.result_code; | |
69 | } | ||
70 | 2 | char const* Error::getMessage() const noexcept | |
71 | { | ||
72 | 2 | return gate_result_text(this->info.result_code); | |
73 | } | ||
74 | 2 | char const* Error::getSource() const noexcept | |
75 | { | ||
76 | 2 | return this->info.source; | |
77 | } | ||
78 | 1 | int32_t Error::getErrorCode() const noexcept | |
79 | { | ||
80 | 1 | return this->info.error_code; | |
81 | } | ||
82 | |||
83 | |||
84 | |||
85 | 25 | Exception::Exception(result_t result, char const* msg, char const* src, int32_t errCode) noexcept | |
86 | { | ||
87 | 25 | gate_mem_clear(&this->info, sizeof(this->info)); | |
88 | 25 | this->info.result_code = result; | |
89 | 25 | this->info.error_code = errCode; | |
90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (msg == NULL) |
91 | { | ||
92 | ✗ | msg = gate_result_text(result); | |
93 | } | ||
94 | 25 | size_t msglen = gate_str_length(msg); | |
95 | 25 | size_t srclen = gate_str_length(src); | |
96 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (msglen >= sizeof(this->info.message)) |
97 | { | ||
98 | ✗ | msglen = sizeof(this->info.message) - 1; | |
99 | } | ||
100 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
|
25 | if (srclen >= sizeof(this->info.source)) |
101 | { | ||
102 | 1 | srclen = sizeof(this->info.source) - 1; | |
103 | } | ||
104 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | if (msglen > 0) |
105 | { | ||
106 | 25 | gate_mem_copy(this->info.message, msg, msglen); | |
107 | } | ||
108 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2 times.
|
25 | if (srclen > 0) |
109 | { | ||
110 | 23 | gate_mem_copy(this->info.source, src, srclen); | |
111 | } | ||
112 | 25 | this->info.message[msglen] = 0; | |
113 | 25 | this->info.source[srclen] = 0; | |
114 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 14 times.
|
25 | if (this->info.error_code == 0) |
115 | { | ||
116 | 11 | this->info.error_code = gate_platform_get_last_error(); | |
117 | } | ||
118 | 25 | } | |
119 | ✗ | Exception::Exception(exception_info_t const& xinfo) | |
120 | { | ||
121 | ✗ | Mem::copy(this->info, xinfo); | |
122 | ✗ | } | |
123 | |||
124 | |||
125 | 50 | Exception::~Exception() noexcept | |
126 | { | ||
127 | 50 | } | |
128 | |||
129 | 17 | result_t Exception::getResult() const noexcept | |
130 | { | ||
131 | 17 | return this->info.result_code; | |
132 | } | ||
133 | 4 | char const* Exception::getMessage() const noexcept | |
134 | { | ||
135 | 4 | return this->info.message; | |
136 | } | ||
137 | 4 | char const* Exception::getSource() const noexcept | |
138 | { | ||
139 | 4 | return this->info.source; | |
140 | } | ||
141 | 2 | int32_t Exception::getErrorCode() const noexcept | |
142 | { | ||
143 | 2 | return this->info.error_code; | |
144 | } | ||
145 | |||
146 | |||
147 | 1 | ExceptionInfo::ExceptionInfo() | |
148 | 1 | : exception_info_t(exception_info_t()) | |
149 | { | ||
150 | 1 | } | |
151 | |||
152 | 2 | ExceptionInfo::ExceptionInfo(exception_info_t const& src) | |
153 | { | ||
154 | 2 | exception_info_t* dest = static_cast<exception_info_t*>(this); | |
155 | 2 | gate_mem_copy(dest, &src, sizeof(exception_info_t)); | |
156 | 2 | } | |
157 | |||
158 | 1 | bool_t ExceptionInfo::failed() const noexcept | |
159 | { | ||
160 | 1 | return GATE_FAILED(this->result_code); | |
161 | } | ||
162 | |||
163 | 1 | bool_t ExceptionInfo::succeeded() const noexcept | |
164 | { | ||
165 | 1 | return GATE_SUCCEEDED(this->result_code); | |
166 | } | ||
167 | |||
168 | 1 | void ExceptionInfo::raise() const | |
169 | { | ||
170 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (GATE_FAILED(this->result_code)) |
171 | { | ||
172 | 1 | raiseException(this->result_code, this->message, this->source, this->error_code); | |
173 | } | ||
174 | ✗ | } | |
175 | |||
176 | |||
177 | ✗ | GATEXX_ATTR_NORETURN void raise(Error errObj) | |
178 | { | ||
179 | #if defined(GATEXX_NO_EXCEPTIONS) | ||
180 | gate::panic(errObj.getResult(), errObj.getSource()); | ||
181 | #else | ||
182 | ✗ | throw errObj; | |
183 | #endif | ||
184 | } | ||
185 | |||
186 | 12 | GATEXX_ATTR_NORETURN void raiseError(result_t resultCode, char const* src, int32_t errCode) | |
187 | { | ||
188 | #if defined(GATE_DEBUG_MODE) | ||
189 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | printf("ERROR: %d %s %d\n", resultCode, src ? src : "??", errCode); |
190 | #endif | ||
191 | |||
192 | #if defined(GATEXX_NO_EXCEPTIONS) | ||
193 | gate::panic(resultCode); | ||
194 | #else | ||
195 | 12 | throw Error(resultCode, src, errCode); | |
196 | #endif | ||
197 | } | ||
198 | |||
199 | ✗ | GATEXX_ATTR_NORETURN void raise(Exception xcptObj) | |
200 | { | ||
201 | ✗ | throw xcptObj; | |
202 | } | ||
203 | |||
204 | |||
205 | 24 | GATEXX_ATTR_NORETURN void raiseException(result_t resultCode, char const* msg, char const* src, int32_t errCode) | |
206 | { | ||
207 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 13 times.
|
24 | if (!msg) |
208 | { | ||
209 | 11 | msg = gate_result_text(resultCode); | |
210 | } | ||
211 | #if defined(GATE_DEBUG_MODE) | ||
212 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
|
24 | printf("EXCEPTION: %d %s [%s]\n", resultCode, msg, src ? src : "??"); |
213 | #endif | ||
214 | |||
215 | #if !defined(GATE_EXCEPTIONS_ADVANCED) | ||
216 | 24 | throw Exception(resultCode, msg, src, errCode); | |
217 | #else | ||
218 | switch (resultCode) | ||
219 | { | ||
220 | case GATE_RESULT_ERROR: throw exceptions::Error(msg, src, errCode); | ||
221 | case GATE_RESULT_FAILED: throw exceptions::Failed(msg, src, errCode); | ||
222 | case GATE_RESULT_CANCELED: throw exceptions::Canceled(msg, src, errCode); | ||
223 | case GATE_RESULT_INVALIDARG: throw exceptions::InvalidArg(msg, src, errCode); | ||
224 | case GATE_RESULT_ACCESSDENIED: throw exceptions::AccessDenied(msg, src, errCode); | ||
225 | case GATE_RESULT_PERMISSIONDENIED: throw exceptions::PermissionDenied(msg, src, errCode); | ||
226 | case GATE_RESULT_NOTDEFINED: throw exceptions::NotDefined(msg, src, errCode); | ||
227 | case GATE_RESULT_NOTAVAILABLE: throw exceptions::NotAvailable(msg, src, errCode); | ||
228 | case GATE_RESULT_NOTIMPLEMENTED: throw exceptions::NotImplemented(msg, src, errCode); | ||
229 | case GATE_RESULT_NOMATCH: throw exceptions::NoMatch(msg, src, errCode); | ||
230 | case GATE_RESULT_NOTSUPPORTED: throw exceptions::NotSupported(msg, src, errCode); | ||
231 | case GATE_RESULT_NOTREQUIRED: throw exceptions::NotRequired(msg, src, errCode); | ||
232 | case GATE_RESULT_NOTREADY: throw exceptions::NotReady(msg, src, errCode); | ||
233 | case GATE_RESULT_SECURITYBREACH: throw exceptions::SecurityBreach(msg, src, errCode); | ||
234 | case GATE_RESULT_ALREADYEXISTS: throw exceptions::AlreadyExists(msg, src, errCode); | ||
235 | case GATE_RESULT_INVALIDSTATE: throw exceptions::InvalidState(msg, src, errCode); | ||
236 | |||
237 | // RESOURCE ACCESS ERRORS | ||
238 | case GATE_RESULT_OUTOFMEMORY: throw exceptions::OutOfMemory(msg, src, errCode); | ||
239 | case GATE_RESULT_OUTOFRESOURCES: throw exceptions::OutOfResources(msg, src, errCode); | ||
240 | case GATE_RESULT_OUTOFBOUNDS: throw exceptions::OutOfBounds(msg, src, errCode); | ||
241 | case GATE_RESULT_NULLPOINTER: throw exceptions::NullPointer(msg, src, errCode); | ||
242 | case GATE_RESULT_BADCAST: throw exceptions::BadCast(msg, src, errCode); | ||
243 | case GATE_RESULT_ARITHMETICERROR: throw exceptions::ArithmeticError(msg, src, errCode); | ||
244 | case GATE_RESULT_OVERFLOW: throw exceptions::Overflow(msg, src, errCode); | ||
245 | case GATE_RESULT_UNDERFLOW: throw exceptions::Underflow(msg, src, errCode); | ||
246 | case GATE_RESULT_LOCKED: throw exceptions::Locked(msg, src, errCode); | ||
247 | case GATE_RESULT_TIMEOUT: throw exceptions::Timeout(msg, src, errCode); | ||
248 | case GATE_RESULT_BADADDRESS: throw exceptions::BadAddress(msg, src, errCode); | ||
249 | case GATE_RESULT_BLOCKED: throw exceptions::Blocked(msg, src, errCode); | ||
250 | case GATE_RESULT_DEVICEERROR: throw exceptions::DeviceError(msg, src, errCode); | ||
251 | |||
252 | // EXECUTION ERRORS | ||
253 | case GATE_RESULT_EXECUTIONFAILED: throw exceptions::ExecutionFailed(msg, src, errCode); | ||
254 | case GATE_RESULT_EXECUTIONINTERRUPTED: throw exceptions::ExecutionInterrupted(msg, src, errCode); | ||
255 | case GATE_RESULT_CRITICALERROR: throw exceptions::CriticalError(msg, src, errCode); | ||
256 | case GATE_RESULT_UNKNOWNEXCEPTION: throw exceptions::UnknownException(msg, src, errCode); | ||
257 | case GATE_RESULT_PRECONDITIONFAILED: throw exceptions::PreconditionFailed(msg, src, errCode); | ||
258 | case GATE_RESULT_PREPARATIONFAILED: throw exceptions::PreparationFailed(msg, src, errCode); | ||
259 | case GATE_RESULT_BADINSTRUCTION: throw exceptions::BadInstruction(msg, src, errCode); | ||
260 | |||
261 | // DATA ERRORS | ||
262 | case GATE_RESULT_INVALIDHEADER: throw exceptions::InvalidHeader(msg, src, errCode); | ||
263 | case GATE_RESULT_INVALIDDATA: throw exceptions::InvalidData(msg, src, errCode); | ||
264 | case GATE_RESULT_INVALIDCONTENT: throw exceptions::InvalidContent(msg, src, errCode); | ||
265 | case GATE_RESULT_INCORRECTSIZE: throw exceptions::IncorrectSize(msg, src, errCode); | ||
266 | case GATE_RESULT_INCORRECTTYPE: throw exceptions::IncorrectType(msg, src, errCode); | ||
267 | case GATE_RESULT_ENDOFSTREAM: throw exceptions::EndOfStream(msg, src, errCode); | ||
268 | case GATE_RESULT_INVALIDINPUT: throw exceptions::InvalidInput(msg, src, errCode); | ||
269 | case GATE_RESULT_INVALIDOUTPUT: throw exceptions::InvalidOutput(msg, src, errCode); | ||
270 | case GATE_RESULT_BUFFERTOOSMALL: throw exceptions::BufferTooSmall(msg, src, errCode); | ||
271 | case GATE_RESULT_NODATA: throw exceptions::NoData(msg, src, errCode); | ||
272 | |||
273 | // PROGRAM ERRORS | ||
274 | case GATE_RESULT_APPLICATIONERROR: throw exceptions::ApplicationError(msg, src, errCode); | ||
275 | case GATE_RESULT_LOGICALERROR: throw exceptions::LogicalError(msg, src, errCode); | ||
276 | case GATE_RESULT_USERERROR: throw exceptions::UserError(msg, src, errCode); | ||
277 | |||
278 | // UNSPECIFIED ERRORS | ||
279 | case GATE_RESULT_UNKNOWNERROR: throw exceptions::UnknownError(msg, src, errCode); | ||
280 | default: throw Exception(resultCode, msg, src, errCode); | ||
281 | } | ||
282 | #endif | ||
283 | } | ||
284 | |||
285 | 1 | gate_exception_info_t catchCurrentException() noexcept | |
286 | { | ||
287 | gate_exception_info_t ret; | ||
288 | 1 | gate_mem_clear(&ret, sizeof(ret)); | |
289 | try | ||
290 | { | ||
291 | #if __cplusplus >= 201103L | ||
292 | 2 | std::exception_ptr xcpt_ptr = std::current_exception(); | |
293 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (xcpt_ptr) |
294 | 2 | std::rethrow_exception(xcpt_ptr); | |
295 | ✗ | ret.result_code = results::Ok; | |
296 | #else | ||
297 | throw; | ||
298 | #endif | ||
299 | } | ||
300 | 2 | catch (Throwable const& th) | |
301 | { | ||
302 | 1 | ret.result_code = th.getResult(); | |
303 | 1 | ret.error_code = th.getErrorCode(); | |
304 | 1 | gate_str_print_text(ret.message, sizeof(ret.message), th.getMessage(), gate_str_length(th.getMessage())); | |
305 | 1 | gate_str_print_text(ret.source, sizeof(ret.source), th.getSource(), gate_str_length(th.getSource())); | |
306 | } | ||
307 | ✗ | catch (...) | |
308 | { | ||
309 | ✗ | ret.result_code = results::UnknownException; | |
310 | } | ||
311 | 1 | return ret; | |
312 | } | ||
313 | |||
314 | 6 | gate_exception_info_t catchException(IRunnable& runner) noexcept | |
315 | { | ||
316 | gate_exception_info_t ret; | ||
317 | 6 | gate_mem_clear(&ret, sizeof(ret)); | |
318 | try | ||
319 | { | ||
320 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
6 | runner.run(); |
321 | 2 | ret.result_code = results::Ok; | |
322 | } | ||
323 | 2 | catch (Throwable const& th) | |
324 | { | ||
325 | 1 | ret.result_code = th.getResult(); | |
326 | 1 | ret.error_code = th.getErrorCode(); | |
327 | 1 | gate_str_print_text(ret.message, sizeof(ret.message), th.getMessage(), gate_str_length(th.getMessage())); | |
328 | 1 | gate_str_print_text(ret.source, sizeof(ret.source), th.getSource(), gate_str_length(th.getSource())); | |
329 | } | ||
330 | 1 | catch (...) | |
331 | { | ||
332 | 1 | ret.result_code = results::UnknownException; | |
333 | } | ||
334 | 4 | return ret; | |
335 | } | ||
336 | 5943 | gate_exception_info_t catchException(gate_entrypoint_t dispatcher, void* param) noexcept | |
337 | { | ||
338 | gate_exception_info_t ret; | ||
339 | 5943 | gate_mem_clear(&ret, sizeof(ret)); | |
340 | try | ||
341 | { | ||
342 |
2/2✓ Branch 1 taken 5942 times.
✓ Branch 2 taken 1 times.
|
5943 | ret.result_code = dispatcher(param); |
343 | } | ||
344 | 2 | catch (Throwable const& th) | |
345 | { | ||
346 | 1 | ret.result_code = th.getResult(); | |
347 | 1 | ret.error_code = th.getErrorCode(); | |
348 | 1 | gate_str_print_text(ret.message, sizeof(ret.message), th.getMessage(), gate_str_length(th.getMessage())); | |
349 | 1 | gate_str_print_text(ret.source, sizeof(ret.source), th.getSource(), gate_str_length(th.getSource())); | |
350 | } | ||
351 | ✗ | catch (...) | |
352 | { | ||
353 | ✗ | ret.result_code = results::UnknownException; | |
354 | } | ||
355 | 5943 | return ret; | |
356 | } | ||
357 | |||
358 | 1025 | Result<Void, result_t> makeResult(result_t const& resultCode) | |
359 | { | ||
360 | 1025 | Result<Void, result_t> ret; | |
361 |
2/2✓ Branch 0 taken 1018 times.
✓ Branch 1 taken 7 times.
|
1025 | if (GATE_SUCCEEDED(resultCode)) |
362 | { | ||
363 |
1/2✓ Branch 1 taken 1018 times.
✗ Branch 2 not taken.
|
1018 | ret.createValue(Void()); |
364 | } | ||
365 | else | ||
366 | { | ||
367 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | ret.createError(resultCode); |
368 | } | ||
369 | 1025 | return ret; | |
370 | } | ||
371 | |||
372 | ✗ | ResultValue<result_t, ResultErrorId> makeErr(result_t const& errCode) | |
373 | { | ||
374 | ✗ | return ResultValue<result_t, ResultErrorId>(errCode); | |
375 | } | ||
376 | |||
377 | ✗ | ResultValue<result_t, ResultErrorId> makeErr(results::ResultType const& errCode) | |
378 | { | ||
379 | ✗ | return ResultValue<result_t, ResultErrorId>(static_cast<gate_result_t>(errCode)); | |
380 | } | ||
381 | |||
382 | |||
383 | } // end of namespace gate | ||
384 |