GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_exceptions.cpp
Date: 2026-05-04 21:11:01
Exec Total Coverage
Lines: 127 136 93.4%
Functions: 29 31 93.5%
Branches: 28 36 77.8%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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 !defined(GATEXX_NO_EXCEPTIONS)
38 # if __cplusplus >= 201103L
39 # include <exception>
40 # endif
41 #endif
42
43 namespace gate
44 {
45
46 166 Throwable::~Throwable() noexcept
47 {
48
49 166 }
50
51
52 13 Error::Error(result_t result, char const* source, int32_t errCode) noexcept
53 {
54 13 gate_mem_clear(&this->info, sizeof(this->info));
55 13 this->info.result_code = result;
56 13 this->info.error_code = errCode;
57 13 this->info.source = source;
58
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
13 if (this->info.error_code == 0)
59 {
60 12 this->info.error_code = gate_platform_get_last_error();
61 }
62 13 }
63
64 26 Error::~Error() noexcept
65 {
66 26 }
67
68 1 result_t Error::getResult() const noexcept
69 {
70 1 return this->info.result_code;
71 }
72 2 char const* Error::getMessage() const noexcept
73 {
74 2 return gate_result_text(this->info.result_code);
75 }
76 2 char const* Error::getSource() const noexcept
77 {
78 2 return this->info.source;
79 }
80 1 int32_t Error::getErrorCode() const noexcept
81 {
82 1 return this->info.error_code;
83 }
84
85
86
87 66 Exception::Exception(result_t result, char const* msg, char const* src, int32_t errCode) noexcept
88 {
89 66 gate_mem_clear(&this->info, sizeof(this->info));
90 66 this->info.result_code = result;
91 66 this->info.error_code = errCode;
92
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
66 if (msg == NULL)
93 {
94 1 msg = gate_result_text(result);
95 }
96 66 size_t msglen = gate_str_length(msg);
97 66 size_t srclen = gate_str_length(src);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (msglen >= sizeof(this->info.message))
99 {
100 msglen = sizeof(this->info.message) - 1;
101 }
102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
66 if (srclen >= sizeof(this->info.source))
103 {
104 1 srclen = sizeof(this->info.source) - 1;
105 }
106
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (msglen > 0)
107 {
108 66 gate_mem_copy(this->info.message, msg, msglen);
109 }
110
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 4 times.
66 if (srclen > 0)
111 {
112 62 gate_mem_copy(this->info.source, src, srclen);
113 }
114 66 this->info.message[msglen] = 0;
115 66 this->info.source[srclen] = 0;
116
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 16 times.
66 if (this->info.error_code == 0)
117 {
118 50 this->info.error_code = gate_platform_get_last_error();
119 }
120 66 }
121 1 Exception::Exception(exception_info_t const& xinfo)
122 {
123 1 Mem::copy(this->info, xinfo);
124 1 }
125
126
127 140 Exception::~Exception() noexcept
128 {
129 140 }
130
131 23 result_t Exception::getResult() const noexcept
132 {
133 23 return this->info.result_code;
134 }
135 42 char const* Exception::getMessage() const noexcept
136 {
137 42 return this->info.message;
138 }
139 40 char const* Exception::getSource() const noexcept
140 {
141 40 return this->info.source;
142 }
143 22 int32_t Exception::getErrorCode() const noexcept
144 {
145 22 return this->info.error_code;
146 }
147
148
149 657 ExceptionInfo::ExceptionInfo()
150 657 : exception_info_t(exception_info_t())
151 {
152 657 this->result_code = results::Ok;
153 657 }
154
155 1 ExceptionInfo::ExceptionInfo(result_t result, int32_t errorCode, char const* source, char const* message)
156 {
157 1 gate_exception_info_init(this, result, errorCode, source, message);
158 1 }
159
160
161 29 ExceptionInfo::ExceptionInfo(exception_info_t const& src)
162 {
163 29 exception_info_t* dest = static_cast<exception_info_t*>(this);
164 29 gate_mem_copy(dest, &src, sizeof(exception_info_t));
165 29 }
166
167 104 bool_t ExceptionInfo::failed() const noexcept
168 {
169 104 return GATE_FAILED(this->result_code);
170 }
171
172 19 bool_t ExceptionInfo::succeeded() const noexcept
173 {
174 19 return GATE_SUCCEEDED(this->result_code);
175 }
176
177 1 void ExceptionInfo::raise() const
178 {
179
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_FAILED(this->result_code))
180 {
181 1 raiseException(this->result_code, this->message, this->source, this->error_code);
182 }
183 }
184
185
186 GATEXX_ATTR_NORETURN void raise(Error errObj)
187 {
188 #if defined(GATEXX_NO_EXCEPTIONS)
189 gate::panic(errObj.getResult(), errObj.getSource());
190 #else
191 throw errObj;
192 #endif
193 }
194
195 12 GATEXX_ATTR_NORETURN void raiseError(result_t resultCode, char const* src, int32_t errCode)
196 {
197 #if defined(GATE_DEBUG_MODE)
198
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 printf("ERROR: %d %s %d\n", resultCode, src ? src : "??", errCode);
199 #endif
200
201 #if defined(GATEXX_NO_EXCEPTIONS)
202 gate::panic(resultCode, src);
203 #else
204 12 throw Error(resultCode, src, errCode);
205 #endif
206 }
207
208 1 GATEXX_ATTR_NORETURN void raise(Exception xcptObj)
209 {
210 #if defined(GATEXX_NO_EXCEPTIONS)
211 gate::panic(xcptObj.getResult(), xcptObj.getSource());
212 #else
213 1 throw xcptObj;
214 #endif
215 }
216
217
218 63 GATEXX_ATTR_NORETURN void raiseException(result_t resultCode, char const* msg, char const* src, int32_t errCode)
219 {
220
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 21 times.
63 if (!msg)
221 {
222 42 msg = gate_result_text(resultCode);
223 }
224 #if defined(GATE_DEBUG_MODE)
225
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 3 times.
63 printf("EXCEPTION: %d %s [%s]\n", resultCode, msg, src ? src : "??");
226 #endif
227
228 #if defined(GATEXX_NO_EXCEPTIONS)
229 gate::panic(resultCode, src);
230 #elif !defined(GATE_EXCEPTIONS_ADVANCED)
231 63 throw Exception(resultCode, msg, src, errCode);
232 #else
233 switch (resultCode)
234 {
235 case GATE_RESULT_ERROR: throw exceptions::Error(msg, src, errCode);
236 case GATE_RESULT_FAILED: throw exceptions::Failed(msg, src, errCode);
237 case GATE_RESULT_CANCELED: throw exceptions::Canceled(msg, src, errCode);
238 case GATE_RESULT_INVALIDARG: throw exceptions::InvalidArg(msg, src, errCode);
239 case GATE_RESULT_ACCESSDENIED: throw exceptions::AccessDenied(msg, src, errCode);
240 case GATE_RESULT_PERMISSIONDENIED: throw exceptions::PermissionDenied(msg, src, errCode);
241 case GATE_RESULT_NOTDEFINED: throw exceptions::NotDefined(msg, src, errCode);
242 case GATE_RESULT_NOTAVAILABLE: throw exceptions::NotAvailable(msg, src, errCode);
243 case GATE_RESULT_NOTIMPLEMENTED: throw exceptions::NotImplemented(msg, src, errCode);
244 case GATE_RESULT_NOMATCH: throw exceptions::NoMatch(msg, src, errCode);
245 case GATE_RESULT_NOTSUPPORTED: throw exceptions::NotSupported(msg, src, errCode);
246 case GATE_RESULT_NOTREQUIRED: throw exceptions::NotRequired(msg, src, errCode);
247 case GATE_RESULT_NOTREADY: throw exceptions::NotReady(msg, src, errCode);
248 case GATE_RESULT_SECURITYBREACH: throw exceptions::SecurityBreach(msg, src, errCode);
249 case GATE_RESULT_ALREADYEXISTS: throw exceptions::AlreadyExists(msg, src, errCode);
250 case GATE_RESULT_INVALIDSTATE: throw exceptions::InvalidState(msg, src, errCode);
251
252 // RESOURCE ACCESS ERRORS
253 case GATE_RESULT_OUTOFMEMORY: throw exceptions::OutOfMemory(msg, src, errCode);
254 case GATE_RESULT_OUTOFRESOURCES: throw exceptions::OutOfResources(msg, src, errCode);
255 case GATE_RESULT_OUTOFBOUNDS: throw exceptions::OutOfBounds(msg, src, errCode);
256 case GATE_RESULT_NULLPOINTER: throw exceptions::NullPointer(msg, src, errCode);
257 case GATE_RESULT_BADCAST: throw exceptions::BadCast(msg, src, errCode);
258 case GATE_RESULT_ARITHMETICERROR: throw exceptions::ArithmeticError(msg, src, errCode);
259 case GATE_RESULT_OVERFLOW: throw exceptions::Overflow(msg, src, errCode);
260 case GATE_RESULT_UNDERFLOW: throw exceptions::Underflow(msg, src, errCode);
261 case GATE_RESULT_LOCKED: throw exceptions::Locked(msg, src, errCode);
262 case GATE_RESULT_TIMEOUT: throw exceptions::Timeout(msg, src, errCode);
263 case GATE_RESULT_BADADDRESS: throw exceptions::BadAddress(msg, src, errCode);
264 case GATE_RESULT_BLOCKED: throw exceptions::Blocked(msg, src, errCode);
265 case GATE_RESULT_DEVICEERROR: throw exceptions::DeviceError(msg, src, errCode);
266
267 // EXECUTION ERRORS
268 case GATE_RESULT_EXECUTIONFAILED: throw exceptions::ExecutionFailed(msg, src, errCode);
269 case GATE_RESULT_EXECUTIONINTERRUPTED: throw exceptions::ExecutionInterrupted(msg, src, errCode);
270 case GATE_RESULT_CRITICALERROR: throw exceptions::CriticalError(msg, src, errCode);
271 case GATE_RESULT_UNKNOWNEXCEPTION: throw exceptions::UnknownException(msg, src, errCode);
272 case GATE_RESULT_PRECONDITIONFAILED: throw exceptions::PreconditionFailed(msg, src, errCode);
273 case GATE_RESULT_PREPARATIONFAILED: throw exceptions::PreparationFailed(msg, src, errCode);
274 case GATE_RESULT_BADINSTRUCTION: throw exceptions::BadInstruction(msg, src, errCode);
275
276 // DATA ERRORS
277 case GATE_RESULT_INVALIDHEADER: throw exceptions::InvalidHeader(msg, src, errCode);
278 case GATE_RESULT_INVALIDDATA: throw exceptions::InvalidData(msg, src, errCode);
279 case GATE_RESULT_INVALIDCONTENT: throw exceptions::InvalidContent(msg, src, errCode);
280 case GATE_RESULT_INCORRECTSIZE: throw exceptions::IncorrectSize(msg, src, errCode);
281 case GATE_RESULT_INCORRECTTYPE: throw exceptions::IncorrectType(msg, src, errCode);
282 case GATE_RESULT_ENDOFSTREAM: throw exceptions::EndOfStream(msg, src, errCode);
283 case GATE_RESULT_INVALIDINPUT: throw exceptions::InvalidInput(msg, src, errCode);
284 case GATE_RESULT_INVALIDOUTPUT: throw exceptions::InvalidOutput(msg, src, errCode);
285 case GATE_RESULT_BUFFERTOOSMALL: throw exceptions::BufferTooSmall(msg, src, errCode);
286 case GATE_RESULT_NODATA: throw exceptions::NoData(msg, src, errCode);
287
288 // PROGRAM ERRORS
289 case GATE_RESULT_APPLICATIONERROR: throw exceptions::ApplicationError(msg, src, errCode);
290 case GATE_RESULT_LOGICALERROR: throw exceptions::LogicalError(msg, src, errCode);
291 case GATE_RESULT_USERERROR: throw exceptions::UserError(msg, src, errCode);
292
293 // UNSPECIFIED ERRORS
294 case GATE_RESULT_UNKNOWNERROR: throw exceptions::UnknownError(msg, src, errCode);
295 default: throw Exception(resultCode, msg, src, errCode);
296 }
297 #endif
298 }
299
300 19 gate_exception_info_t catchCurrentException() noexcept
301 {
302 gate_exception_info_t ret;
303 19 gate_mem_clear(&ret, sizeof(ret));
304
305 #if defined(GATEXX_NO_EXCEPTIONS)
306 ret.result_code = results::Ok;
307 #else
308 try
309 {
310 #if __cplusplus >= 201103L
311 38 std::exception_ptr xcpt_ptr = std::current_exception();
312
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 if (xcpt_ptr)
313 38 std::rethrow_exception(xcpt_ptr);
314 ret.result_code = results::Ok;
315 #else
316 throw;
317 #endif
318 }
319 34 catch (Throwable const& th)
320 {
321 17 ret.result_code = th.getResult();
322 17 ret.error_code = th.getErrorCode();
323 17 gate_str_print_text(ret.message, sizeof(ret.message), th.getMessage(), gate_str_length(th.getMessage()));
324 17 gate_str_print_text(ret.source, sizeof(ret.source), th.getSource(), gate_str_length(th.getSource()));
325 }
326 2 catch (...)
327 {
328 2 ret.result_code = results::UnknownException;
329 }
330 #endif
331 19 return ret;
332 }
333
334 29 gate_exception_info_t catchException(IRunnable& runner) noexcept
335 {
336 gate_exception_info_t ret;
337 29 gate_mem_clear(&ret, sizeof(ret));
338
339 #if defined(GATEXX_NO_EXCEPTIONS)
340 runner.run();
341 ret.result_code = results::Ok;
342 #else
343 try
344 {
345
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 5 times.
29 runner.run();
346 22 ret.result_code = results::Ok;
347 }
348 6 catch (Throwable const& th)
349 {
350 3 ret.result_code = th.getResult();
351 3 ret.error_code = th.getErrorCode();
352 3 gate_str_print_text(ret.message, sizeof(ret.message), th.getMessage(), gate_str_length(th.getMessage()));
353 3 gate_str_print_text(ret.source, sizeof(ret.source), th.getSource(), gate_str_length(th.getSource()));
354 }
355 2 catch (...)
356 {
357 2 ret.result_code = results::UnknownException;
358 }
359 #endif
360 27 return ret;
361 }
362 6524 gate_exception_info_t catchException(gate_entrypoint_t dispatcher, void* param) noexcept
363 {
364 gate_exception_info_t ret;
365 6524 gate_mem_clear(&ret, sizeof(ret));
366
367 #if defined(GATEXX_NO_EXCEPTIONS)
368 ret.result_code = dispatcher(param);
369 #else
370 try
371 {
372
2/2
✓ Branch 1 taken 6523 times.
✓ Branch 2 taken 1 times.
6524 ret.result_code = dispatcher(param);
373 }
374 2 catch (Throwable const& th)
375 {
376 1 ret.result_code = th.getResult();
377 1 ret.error_code = th.getErrorCode();
378 1 gate_str_print_text(ret.message, sizeof(ret.message), th.getMessage(), gate_str_length(th.getMessage()));
379 1 gate_str_print_text(ret.source, sizeof(ret.source), th.getSource(), gate_str_length(th.getSource()));
380 }
381 catch (...)
382 {
383 ret.result_code = results::UnknownException;
384 }
385 #endif
386 6524 return ret;
387 }
388
389 1144 Result<Void, result_t> makeResult(result_t const& resultCode)
390 {
391 1144 Result<Void, result_t> ret;
392
2/2
✓ Branch 0 taken 1137 times.
✓ Branch 1 taken 7 times.
1144 if (GATE_SUCCEEDED(resultCode))
393 {
394
1/2
✓ Branch 1 taken 1137 times.
✗ Branch 2 not taken.
1137 ret.createValue(Void());
395 }
396 else
397 {
398
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 ret.createError(resultCode);
399 }
400 1144 return ret;
401 }
402
403 7 VoidResult makeOk()
404 {
405 7 VoidResult ret;
406
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 ret.createValue(Void());
407 7 return ret;
408 }
409
410
411 ResultValue<result_t, ResultErrorId> makeErr(result_t const& errCode)
412 {
413 return ResultValue<result_t, ResultErrorId>(errCode);
414 }
415
416 1 ResultValue<result_t, ResultErrorId> makeErrResult(results::ResultType const& errCode)
417 {
418 1 return ResultValue<result_t, ResultErrorId>(static_cast<gate_result_t>(errCode));
419 }
420
421
422 } // end of namespace gate
423