GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_exceptions.cpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 109 128 85.2%
Functions: 24 29 82.8%
Branches: 26 34 76.5%

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