GCC Code Coverage Report


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