GCC Code Coverage Report


Directory: src/gate/
File: src/gate/exceptions.hpp
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 59 82 72.0%
Functions: 51 74 68.9%
Branches: 11 30 36.7%

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 /** @file
30 * @brief C++ exception base classes and utilities
31 * @ingroup gatecore_cpp
32 */
33
34 #ifndef GATE_EXECEPTIONS_HPP_INCLUDED
35 #define GATE_EXECEPTIONS_HPP_INCLUDED
36
37 #include "gate/gate_core_api.hpp"
38 #include "gate/gatetypes.hpp"
39 #include "gate/results.hpp"
40 #include "gate/memalloc.hpp"
41
42 namespace gate
43 {
44
45 /// @brief
46 class GATE_CORE_CPP_API Throwable
47 {
48 public:
49 virtual ~Throwable() noexcept;
50
51 virtual result_t getResult() const noexcept = 0;
52 virtual char const* getMessage() const noexcept = 0;
53 virtual char const* getSource() const noexcept = 0;
54 virtual int32_t getErrorCode() const noexcept = 0;
55
56 };
57
58
59
60 /// @brief
61 class GATE_CORE_CPP_API Error : public Throwable
62 {
63 public:
64 explicit Error(result_t result, char const* source = 0, int32_t errCode = 0) noexcept;
65 virtual ~Error() noexcept;
66
67 virtual result_t getResult() const noexcept;
68 virtual char const* getMessage() const noexcept;
69 virtual char const* getSource() const noexcept;
70 virtual int32_t getErrorCode() const noexcept;
71
72 private:
73 gate_error_info_t info;
74 };
75
76
77 /// @brief
78 class GATE_CORE_CPP_API Exception : public Throwable
79 {
80 public:
81 explicit Exception(result_t result, char const* msg = 0, char const* src = 0, int32_t errCode = 0) noexcept;
82 explicit Exception(exception_info_t const& xinfo);
83 virtual ~Exception() noexcept;
84
85 virtual result_t getResult() const noexcept;
86 virtual char const* getMessage() const noexcept;
87 virtual char const* getSource() const noexcept;
88 virtual int32_t getErrorCode() const noexcept;
89
90 private:
91 exception_info_t info;
92 };
93
94
95 /// @brief
96 class GATE_CORE_CPP_API ExceptionInfo : public exception_info_t
97 {
98 public:
99 ExceptionInfo();
100 ExceptionInfo(exception_info_t const& src);
101
102 bool_t failed() const noexcept;
103 bool_t succeeded() const noexcept;
104 void raise() const;
105 };
106
107
108 /// @brief
109 /// @param errObj
110 /// @return
111 GATEXX_ATTR_NORETURN GATE_CORE_CPP_API extern void raise(Error errObj);
112
113
114 /// @brief
115 /// @param resultCode
116 /// @param src
117 /// @param errCode
118 /// @return
119 GATEXX_ATTR_NORETURN GATE_CORE_CPP_API extern void raiseError(result_t resultCode, char const* src = 0, int32_t errCode = 0);
120
121 #define GATEXX_CHECK_ERROR(resultCode) do { if(GATE_FAILED(resultCode)) ::gate::raiseError(resultCode, GATE_CURRENT_FUNCTION_NAME, 0); } while(0)
122 #define GATEXX_RAISE_ERROR(resultCode) ::gate::raiseError(resultCode, GATE_CURRENT_FUNCTION_NAME, 0)
123
124
125 /// @brief
126 /// @param xcptObj
127 /// @return
128 GATEXX_ATTR_NORETURN GATE_CORE_CPP_API extern void raise(Exception xcptObj);
129
130
131 /// @brief
132 /// @param resultCode
133 /// @param msg
134 /// @param src
135 /// @param errCode
136 /// @return
137 GATEXX_ATTR_NORETURN GATE_CORE_CPP_API extern void raiseException(result_t resultCode, char const* msg = 0, char const* src = 0, int32_t errCode = 0);
138
139 #define GATEXX_CHECK_EXCEPTION(resultCode) do { if(GATE_FAILED(resultCode)) ::gate::raiseException(resultCode, 0, GATE_CURRENT_FUNCTION_NAME, 0); } while(0)
140 #define GATEXX_RAISE_EXCEPTION(resultCode, message, nativeErrorCode) ::gate::raiseException(resultCode, message, GATE_CURRENT_FUNCTION_NAME, nativeErrorCode)
141
142 #define GATEXX_RETHROW throw
143
144
145 /// @brief
146 /// @tparam T
147 template<class T>
148 class ErrorPublisher
149 {
150 public:
151 static void publish(T const& errObj, char const* source);
152 };
153
154 template<>
155 class ErrorPublisher<result_t>
156 {
157 public:
158 static void publish(result_t const& errType, char const* source)
159 {
160 raise(Error(errType, source));
161 }
162 };
163
164
165 /// @brief
166 /// @tparam T
167 template<class T>
168 class ExceptionPublisher
169 {
170 public:
171 static void publish(T const& errObj, char const* source);
172 };
173
174 template<>
175 class ExceptionPublisher<result_t>
176 {
177 public:
178 static void publish(result_t const& xcptType, char const* source)
179 {
180 raise(Exception(xcptType, 0, source));
181 }
182 };
183
184
185
186 /// @brief
187 /// @tparam T
188 /// @tparam ID
189 template<class T, class ID>
190 class ResultValue
191 {
192 public:
193 typedef ResultValue<T, ID> self_t;
194 typedef T item_t;
195 private:
196 item_t item;
197 public:
198
199 14 ResultValue(item_t const& src)
200 14 : item(src)
201 {
202 14 }
203 ResultValue(self_t const& src)
204 : item(src.item)
205 {
206 }
207 self_t& operator=(self_t const& src)
208 {
209 this->item = src.item;
210 return *this;
211 }
212 16 ~ResultValue()
213 {
214 16 }
215 item_t& get() noexcept
216 {
217 return this->item;
218 }
219 16 item_t const& get() const noexcept
220 {
221 16 return this->item;
222 }
223 };
224
225 struct ResultSuccessId {};
226 struct ResultErrorId {};
227
228
229 /// @brief
230 /// @tparam TRESULTTYPE
231 /// @param resultType
232 /// @return
233 template<class TRESULTTYPE>
234 14 ResultValue<TRESULTTYPE, ResultSuccessId> makeOk(TRESULTTYPE const& resultType)
235 {
236 14 return ResultValue<TRESULTTYPE, ResultSuccessId>(resultType);
237 }
238
239
240 /// @brief
241 /// @tparam TERRORTYPE
242 /// @param errType
243 /// @return
244 template<class TERRORTYPE>
245 ResultValue<TERRORTYPE, ResultErrorId> makeErr(TERRORTYPE const& errType)
246 {
247 return ResultValue<TERRORTYPE, ResultErrorId>(errType);
248 }
249
250
251 /// @brief
252 /// @param errCode
253 /// @return
254 GATE_CORE_CPP_API extern ResultValue<result_t, ResultErrorId> makeErr(result_t const& errCode);
255
256
257 /// @brief
258 /// @param errCode
259 /// @return
260 GATE_CORE_CPP_API extern ResultValue<result_t, ResultErrorId> makeErr(results::ResultType const& errCode);
261
262 struct Void {};
263
264
265 /// @brief
266 /// @tparam T
267 /// @tparam E
268 template<class T = Void, class E = result_t>
269 class Result
270 {
271 public:
272 typedef T value_t;
273 typedef E error_t;
274 typedef Result<T, E> self_t;
275
276 typedef ResultValue<T, ResultSuccessId> ResultSuccessType;
277 typedef ResultValue<E, ResultErrorId> ResultErrorType;
278 private:
279 value_t* ptrValue;
280 error_t* ptrError;
281 union
282 {
283 gate_c_maxalign_t dummy;
284 char valueContent[sizeof(value_t)];
285 char errorContent[sizeof(error_t)];
286 } content;
287
288 public:
289 2088 bool_t empty() const noexcept
290 {
291
2/4
✓ Branch 0 taken 1046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1046 times.
✗ Branch 3 not taken.
2088 return (this->ptrValue == NULL) && (this->ptrError == NULL);
292 }
293
294
295 void createValue()
296 {
297 if (!this->empty())
298 {
299 GATEXX_RAISE_ERROR(results::InvalidState);
300 }
301 else
302 {
303 value_t* ptrMem = reinterpret_cast<value_t*>(&this->content.valueContent[0]);
304 gate::constructType(ptrMem);
305 this->ptrValue = ptrMem;
306 }
307 }
308 1056 void createValue(value_t const& src)
309 {
310
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1039 times.
1056 if (!this->empty())
311 {
312 GATEXX_RAISE_ERROR(results::InvalidState);
313 }
314 else
315 {
316 1056 value_t* ptrMem = reinterpret_cast<value_t*>(&this->content.valueContent[0]);
317 1056 gate::copyConstructType(ptrMem, src);
318 1056 this->ptrValue = ptrMem;
319 }
320 1056 }
321
322 void createError()
323 {
324 if (!this->empty())
325 {
326 GATEXX_RAISE_ERROR(results::InvalidState);
327 }
328 else
329 {
330 error_t* ptrMem = reinterpret_cast<error_t*>(&this->content.errorContent[0]);
331 gate::constructType(ptrMem);
332 this->ptrError = ptrMem;
333 }
334 }
335
336 14 void createError(error_t const& src)
337 {
338
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
14 if (!this->empty())
339 {
340 GATEXX_RAISE_ERROR(results::InvalidState);
341 }
342 else
343 {
344 14 error_t* ptrMem = reinterpret_cast<error_t*>(&this->content.errorContent[0]);
345 14 gate::copyConstructType(ptrMem, src);
346 14 this->ptrError = ptrMem;
347 }
348 14 }
349
350 1038 Result()
351 : ptrValue(NULL),
352 ptrError(NULL),
353 1038 content()
354 {
355 1038 }
356
357 14 Result(ResultSuccessType const& successType)
358 : ptrValue(NULL),
359 ptrError(NULL),
360 14 content()
361 {
362 14 this->createValue(successType.get());
363 14 }
364
365 Result(ResultErrorType const& errorType)
366 : ptrValue(NULL),
367 ptrError(NULL),
368 content()
369 {
370 this->createError(errorType.get());
371 }
372
373 Result(self_t const& src)
374 : ptrValue(NULL),
375 ptrError(NULL),
376 content()
377 {
378 if (src.hasValue())
379 {
380 this->createValue(src.value());
381 }
382 else if (src.hasError())
383 {
384 this->createError(src.error());
385 }
386 else
387 {
388 // An empty result is not allowed to be copied
389 GATEXX_RAISE_ERROR(results::InvalidState);
390 }
391 }
392
393 1063 void reset()
394 {
395
2/2
✓ Branch 0 taken 1039 times.
✓ Branch 1 taken 7 times.
1063 if (this->ptrValue)
396 {
397 1056 destructType(this->ptrValue);
398 1056 this->ptrValue = NULL;
399 }
400
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 else if (this->ptrError)
401 {
402 7 destructType(this->ptrError);
403 7 this->ptrError = NULL;
404 }
405 1063 }
406
407 self_t& operator=(self_t const& src)
408 {
409 if (this != &src)
410 {
411 this->reset();
412 if (src.hasValue())
413 {
414 this->createValue(src.value());
415 }
416 else if (src.hasError())
417 {
418 this->createError(src.error());
419 }
420 }
421 return *this;
422 }
423
424 1063 ~Result()
425 {
426 1063 this->reset();
427 1063 }
428
429 1 bool_t hasValue() const noexcept
430 {
431 1 return this->ptrValue != NULL;
432 }
433
434 22 value_t& value() const noexcept
435 {
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
22 if (!this->ptrValue)
437 {
438 gate::panic(results::NullPointer, "Result<>::value()");
439 }
440 22 return *this->ptrValue;
441 }
442
443 14 void checkError(char const* source) const
444 {
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
14 if (this->ptrError)
446 {
447 ErrorPublisher<error_t>::publish(*this->ptrError, source);
448 }
449 14 }
450
451 void checkException(char const* source) const
452 {
453 if (this->ptrError)
454 {
455 ExceptionPublisher<error_t>::publish(*this->ptrError, source);
456 }
457 }
458
459 14 value_t& valueOrError() const
460 {
461 14 checkError("Result::valueOrError");
462 14 return value();
463 }
464
465 value_t& valueOrExcept() const
466 {
467 checkException("Result::valueOrExcept");
468 return value();
469 }
470
471 21 bool_t hasError() const noexcept
472 {
473 21 return this->ptrError != NULL;
474 }
475
476 error_t& error() const noexcept
477 {
478 if (!this->ptrError)
479 {
480 gate::panic(results::NullPointer, "Result<>::error()");
481 }
482 return *this->ptrError;
483 }
484
485 bool_t operator!() const noexcept
486 {
487 return !this->hasValue();
488 }
489 value_t& operator*() noexcept
490 {
491 return this->value();
492 }
493 value_t const& operator*() const noexcept
494 {
495 return this->value();
496 }
497 };
498
499 typedef Result<Void, result_t> VoidResult;
500
501
502 /// @brief
503 /// @tparam TRESULTTYPE
504 /// @param resultCode
505 /// @param resultType
506 /// @return
507 template<class TRESULTTYPE>
508 13 Result<TRESULTTYPE, result_t> makeResult(result_t const& resultCode, TRESULTTYPE const& resultType)
509 {
510 13 Result<TRESULTTYPE, result_t> ret;
511
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (GATE_SUCCEEDED(resultCode))
512 {
513
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 ret.createValue(resultType);
514 }
515 else
516 {
517 ret.createError(resultCode);
518 }
519 13 return ret;
520 }
521
522 // NOTICE: Old compilers like OpenWATCOM cannot link templated ResultValue<E> into Result<T,E>.
523 // Therefore we need a makeErr() that provides the T-Result too.
524 template<class TRESULTTYPE>
525 Result<TRESULTTYPE, result_t> makeErr(result_t const& errorCode, TRESULTTYPE const& resultInfo)
526 {
527 Result<TRESULTTYPE, result_t> ret;
528 ret.createError(errorCode);
529 return ret;
530 }
531 template<class TRESULTTYPE>
532 Result<TRESULTTYPE, result_t> makeErr(results::ResultType const& errorCode, TRESULTTYPE const& resultInfo)
533 {
534 Result<TRESULTTYPE, result_t> ret;
535 ret.createError(static_cast<result_t>(errorCode));
536 return ret;
537 }
538
539
540 GATE_CORE_CPP_API extern Result<Void, result_t> makeResult(result_t const& resultCode);
541
542
543 #if defined(GATE_EXCEPTIONS_ADVANCED)
544
545 namespace exceptions
546 {
547
548 template<int RESULT>
549 class GATE_CORE_CPP_API ResultException : public Exception
550 {
551 public:
552 ResultException(char const* msg = 0, char const* src = 0, int32_t errCode = 0)
553 : Exception(RESULT, (msg ? msg : gate_result_text(RESULT)), src, errCode)
554 {
555 }
556 };
557
558
559 /* GENERIC ERRORS */
560 typedef ResultException<GATE_RESULT_ERROR> Error;
561 typedef ResultException<GATE_RESULT_FAILED> Failed;
562 typedef ResultException<GATE_RESULT_CANCELED> Canceled;
563 typedef ResultException<GATE_RESULT_INVALIDARG> InvalidArg;
564 typedef ResultException<GATE_RESULT_ACCESSDENIED> AccessDenied;
565 typedef ResultException<GATE_RESULT_PERMISSIONDENIED> PermissionDenied;
566 typedef ResultException<GATE_RESULT_NOTDEFINED> NotDefined;
567 typedef ResultException<GATE_RESULT_NOTAVAILABLE> NotAvailable;
568 typedef ResultException<GATE_RESULT_NOTIMPLEMENTED> NotImplemented;
569 typedef ResultException<GATE_RESULT_NOMATCH> NoMatch;
570 typedef ResultException<GATE_RESULT_NOTSUPPORTED> NotSupported;
571 typedef ResultException<GATE_RESULT_NOTREQUIRED> NotRequired;
572 typedef ResultException<GATE_RESULT_NOTREADY> NotReady;
573 typedef ResultException<GATE_RESULT_SECURITYBREACH> SecurityBreach;
574 typedef ResultException<GATE_RESULT_ALREADYEXISTS> AlreadyExists;
575 typedef ResultException<GATE_RESULT_INVALIDSTATE> InvalidState;
576
577 /* RESOURCE ACCESS ERRORS */
578 typedef ResultException<GATE_RESULT_OUTOFMEMORY> OutOfMemory;
579 typedef ResultException<GATE_RESULT_OUTOFRESOURCES> OutOfResources;
580 typedef ResultException<GATE_RESULT_OUTOFBOUNDS> OutOfBounds;
581 typedef ResultException<GATE_RESULT_NULLPOINTER> NullPointer;
582 typedef ResultException<GATE_RESULT_BADCAST> BadCast;
583 typedef ResultException<GATE_RESULT_ARITHMETICERROR> ArithmeticError;
584 typedef ResultException<GATE_RESULT_OVERFLOW> Overflow;
585 typedef ResultException<GATE_RESULT_UNDERFLOW> Underflow;
586 typedef ResultException<GATE_RESULT_LOCKED> Locked;
587 typedef ResultException<GATE_RESULT_TIMEOUT> Timeout;
588 typedef ResultException<GATE_RESULT_BADADDRESS> BadAddress;
589 typedef ResultException<GATE_RESULT_BLOCKED> Blocked;
590 typedef ResultException<GATE_RESULT_DEVICEERROR> DeviceError;
591
592 /* EXECUTION ERRORS */
593 typedef ResultException<GATE_RESULT_EXECUTIONFAILED> ExecutionFailed;
594 typedef ResultException<GATE_RESULT_EXECUTIONINTERRUPTED> ExecutionInterrupted;
595 typedef ResultException<GATE_RESULT_CRITICALERROR> CriticalError;
596 typedef ResultException<GATE_RESULT_UNKNOWNEXCEPTION> UnknownException;
597 typedef ResultException<GATE_RESULT_PRECONDITIONFAILED> PreconditionFailed;
598 typedef ResultException<GATE_RESULT_PREPARATIONFAILED> PreparationFailed;
599 typedef ResultException<GATE_RESULT_BADINSTRUCTION> BadInstruction;
600
601 /* DATA ERRORS */
602 typedef ResultException<GATE_RESULT_INVALIDHEADER> InvalidHeader;
603 typedef ResultException<GATE_RESULT_INVALIDDATA> InvalidData;
604 typedef ResultException<GATE_RESULT_INVALIDCONTENT> InvalidContent;
605 typedef ResultException<GATE_RESULT_INCORRECTSIZE> IncorrectSize;
606 typedef ResultException<GATE_RESULT_INCORRECTTYPE> IncorrectType;
607 typedef ResultException<GATE_RESULT_ENDOFSTREAM> EndOfStream;
608 typedef ResultException<GATE_RESULT_INVALIDINPUT> InvalidInput;
609 typedef ResultException<GATE_RESULT_INVALIDOUTPUT> InvalidOutput;
610 typedef ResultException<GATE_RESULT_BUFFERTOOSMALL> BufferTooSmall;
611 typedef ResultException<GATE_RESULT_NODATA> NoData;
612
613 /* PROGRAM ERRORS */
614 typedef ResultException<GATE_RESULT_APPLICATIONERROR> ApplicationError;
615 typedef ResultException<GATE_RESULT_LOGICALERROR> LogicalError;
616 typedef ResultException<GATE_RESULT_USERERROR> UserError;
617
618 /* UNSPECIFIED ERRORS */
619 typedef ResultException<GATE_RESULT_UNKNOWNERROR> UnknownError;
620
621 } // end of namespace exceptions
622 #endif
623
624 } // end if namespace gate
625
626 #endif
627