MLIB
Loading...
Searching...
No Matches
errorcode.h
Go to the documentation of this file.
1/*
2 Copyright (c) Mircea Neacsu (2014-2025) Licensed under MIT License.
3 This file is part of MLIB project. See LICENSE file for full license terms.
4*/
5
6
8#pragma once
9
56
57#if __has_include("defs.h")
58#include "defs.h"
59#endif
60
61#include <string>
62
63#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) \
64 || (!defined(_MSVC_LANG) && (__cplusplus < 201703L))
65#error "errorcode requires c++17"
66#endif
67
68namespace mlib {
69
70class errfac;
71
72class erc
73{
74public:
87 erc ();
88 explicit erc (int value, level priority = level::error);
89 explicit erc (int value, const mlib::errfac& facility, level priority = level::error);
90 erc (const erc& other);
91 erc (erc&& other);
92
93 ~erc () noexcept (false);
94 erc& operator= (const erc& rhs);
95 erc& operator= (erc&& rhs);
96 operator int () const;
97
99 level priority () const;
100
102 bool is_active () const;
103
105 const errfac& facility () const;
106
107 bool operator== (const erc& other) const;
108 bool operator!= (const erc& other) const;
109
110 void raise () const;
111
112 void reactivate () const;
113 void deactivate () const;
114
115 int code () const;
116
118 std::string message () const;
119 void message (const std::string& m);
120
121 static erc success;
122
123private:
124 // bit fields
125 int value : 24;
126 int priority_ : 4;
127 mutable int active : 1;
128
129 const errfac& facility_;
130 std::string msg;
131
132 friend class errfac;
133};
134
139
141{
142public:
143 // constructors/destructor
144 errfac (const std::string& name = "Error");
145
147 void throw_priority (erc::level pri);
148
150 erc::level throw_priority () const;
151
153 void log_priority (erc::level pri);
154
156 erc::level log_priority () const;
157
159 virtual std::string message (const erc& e) const;
160
162 const std::string& name () const;
163
165 static void Default (errfac* f);
166
168 static errfac& Default ();
169
170 virtual void raise (const erc& e) const;
171 virtual void log (const erc& e) const;
172
173private:
174 erc::level log_level;
175 erc::level throw_level;
176 std::string name_;
177 static errfac* default_facility;
178};
179
180#if (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) \
181 || (!defined(_MSVC_LANG) && (__cplusplus >= 202002L))
182template <class T>
183concept checkable = !std::is_convertible_v<T, int>;
184
201template <checkable T>
202class checked : public erc
203{
204public:
208 : erc ()
209 , obj ()
210 {}
211
213 checked (const T& obj_, const erc& err)
214 : erc (err)
215 , obj (obj_)
216 {}
217
219 checked (const T& obj_, int value = 0, erc::level pri_ = erc::level::error)
220 : erc (value, pri_)
221 , obj (obj_)
222 {}
223
224 checked (T&& obj_, erc&& err)
225 : erc (std::move (err))
226 , obj (std::move (obj_))
227 {}
228
229 checked (T&& obj_, const erc& err)
230 : erc (err)
231 , obj (std::move (obj_))
232 {}
233
235 checked (const checked<T>& other)
236 : erc (other)
237 , obj (other.obj)
238 {}
239
242 : erc (other)
243 , obj (other.obj)
244 {}
245
246 ~checked () noexcept (false) = default;
247
249 checked<T>& operator= (const checked<T>& rhs)
250 {
251 if (&rhs != this)
252 {
253 erc::operator= (rhs);
254 obj = rhs.obj;
255 }
256 return *this;
257 }
258
260 checked<T>& operator= (checked<T>&& rhs)
261 {
262 if (&rhs != this)
263 {
264 *(erc*)this = std::move (rhs);
265 obj = std::move (rhs.obj);
266 }
267 return *this;
268 }
269
271 checked<T>& operator= (const erc& rhs)
272 {
273 erc::operator= (rhs);
274 return *this;
275 }
276
280 {
281 if (code () && priority ())
282 {
283 reactivate ();
284 raise ();
285 }
286 return obj;
287 }
288
289 const T& operator* () const
290 {
291 if (code () && priority ())
292 {
293 reactivate ();
294 raise ();
295 }
296 return obj;
297 }
298
300 {
301 if (code () && priority ())
302 {
303 reactivate ();
304 raise ();
305 }
306 return &obj;
307 }
308 const T* operator->() const
309 {
310 if (code () && priority ())
311 {
312 reactivate ();
313 raise ();
314 }
315 return &obj;
316 }
317
318
319protected:
320 T obj;
321};
322#endif
323
324//----------------------- errfac inlines -------------------------------------
325
328
330inline errfac* errfac::default_facility = &deffac;
331
344
346inline errfac::errfac (const std::string& name)
347 : throw_level (erc::level::error)
348 , log_level (erc::level::warning)
349 , name_ (name)
350{}
351
353{
354 throw_level = (pri < erc::info) ? erc::info : (pri > erc::emerg) ? erc::emerg : pri;
355}
356
358{
359 return throw_level;
360}
361
363{
364 log_level = (pri < erc::info) ? erc::info : (pri > erc::emerg) ? erc::emerg : pri;
365}
366
368{
369 return log_level;
370}
371
372inline const std::string& errfac::name () const
373{
374 return name_;
375}
376
378inline std::string errfac::message (const erc& e) const
379{
380 return std::string ("error ") + std::to_string (e.value);
381}
382
384{
385 return *default_facility;
386}
387
392inline void errfac::Default (errfac* facility)
393{
394 default_facility = facility ? facility : &deffac;
395}
396
405inline void errfac::raise (const erc& e) const
406{
407 if (e.priority_ >= log_level)
408 log (e);
409 if (e.priority_ >= throw_level)
410 {
411 // Make sure this erc is not thrown again
412 e.active = 0;
413 throw e;
414 }
415}
416
419inline void errfac::log (const erc& e) const
420{
421 fprintf (stderr, "%s - %s\n", name ().c_str (), e.message ().c_str ());
422}
423
424//--------------------------- erc inlines -------------------------------------
425
435
437inline erc::erc ()
438 : value{0}
439 , priority_{none}
440 , active{false}
441 , facility_{errfac::Default ()}
442{}
443
445inline erc::erc (int v, level l)
446 : value{v}
447 , priority_{(unsigned short)l}
448 , facility_{errfac::Default ()}
449 , active{true}
450{}
451
453inline erc::erc (int v, const mlib::errfac& f, level l)
454 : value{v}
455 , priority_{(unsigned short)l}
456 , facility_{f}
457 , active{true}
458{}
459
472inline erc::erc (const erc& other)
473 : value{other.value}
474 , priority_{other.priority_}
475 , active{other.active}
476 , facility_{other.facility_}
477 , msg{other.msg}
478{
479 // we are the active error now, the other is deactivated
480 other.active = 0;
481}
482
484inline erc::erc (erc&& other)
485 : value{other.value}
486 , priority_{other.priority_}
487 , active{other.active}
488 , facility_{other.facility_}
489 , msg{other.msg}
490{
491 // we are the active error now, the other is deactivated
492 other.active = 0;
493}
494
496inline erc::~erc () noexcept (false)
497{
498 raise ();
499}
500
512inline erc& erc::operator= (const erc& rhs)
513{
514 if (&rhs != this)
515 {
516 int rhs_active = rhs.active;
517 rhs.active = 0; // prevent rhs from throwing if we throw
518 if (active && priority_)
519 facility_.raise (*this);
520 value = rhs.value;
521 priority_ = rhs.priority_;
522 const_cast<errfac&> (facility_) = rhs.facility_;
523 msg = rhs.msg;
524 active = rhs_active;
525 }
526 return *this;
527}
528
536inline erc& erc::operator= (erc&& rhs)
537{
538 if (&rhs != this)
539 {
540 bool rhs_active = rhs.active;
541 rhs.active = 0; // prevent rhs from throwing if we throw
542 if (active && value && priority_)
543 facility_.raise (*this);
544 value = rhs.value;
545 priority_ = rhs.priority_;
546 const_cast<errfac&>(facility_) = rhs.facility_;
547 msg = rhs.msg;
548 active = rhs_active;
549 }
550 return *this;
551}
552
554{
555 return (erc::level)priority_;
556}
557
558inline bool erc::is_active () const
559{
560 return active;
561}
562
563inline const errfac& erc::facility () const
564{
565 return facility_;
566}
567
576inline bool erc::operator== (const erc& other) const
577{
578 active = false;
579 const_cast<erc&> (other).active = false;
580 if ((!priority_ || !value) && (!other.priority_ || !other.value))
581 return true; // success values are the same
582 if (&facility_ == &other.facility_ && priority_ == other.priority_ && value == other.value)
583 return true;
584
585 return false;
586}
587
596inline bool erc::operator!= (const erc& other) const
597{
598 return !operator== (other);
599}
600
603inline void erc::raise () const
604{
605 if (value && active && priority_)
606 facility_.raise (*this);
607 }
608
615inline int erc::code () const
616{
617 return value;
618}
619
626inline std::string erc::message () const
627{
628 return msg.empty () ? facility_.message (*this) : msg;
629}
630
632inline void erc::message (const std::string& m)
633{
634 msg = m;
635}
636
642inline erc::operator int () const
643{
644 active = 0;
645 return value;
646}
647
649inline void erc::reactivate () const
650{
651 active = 1;
652}
653
659inline void erc::deactivate () const
660{
661 active = 0;
662}
663
665inline erc erc::success{0, erc::none};
666
667} // namespace mlib
Provides a mechanism similar to expected for creating objects associated with error codes.
Definition errorcode.h:203
checked(const checked< T > &other)
Copy constructor.
Definition errorcode.h:235
const T * operator->() const
Definition errorcode.h:308
T * operator->()
Definition errorcode.h:299
checked(const T &obj_, const erc &err)
Constructor using a T and an error code. Both are copy-constructed.
Definition errorcode.h:213
checked(checked< T > &&other)
Move constructor.
Definition errorcode.h:241
checked()
Definition errorcode.h:207
objects returned as a function result or thrown directly.
Definition errorcode.h:73
void reactivate() const
Similar to re-throwing an exception.
Definition errorcode.h:649
bool operator!=(const erc &other) const
Inequality comparison operator.
Definition errorcode.h:596
int code() const
Return numerical value.
Definition errorcode.h:615
std::string message() const
Get logging message.
Definition errorcode.h:626
bool operator==(const erc &other) const
Equality comparison operator.
Definition errorcode.h:576
level priority() const
Return priority value.
Definition errorcode.h:553
~erc() noexcept(false)
Destructor. Call raise() function to see if the error should get logged or thrown.
Definition errorcode.h:496
void deactivate() const
Marks error code as inactive.
Definition errorcode.h:659
static erc success
The SUCCESS indicator.
Definition errorcode.h:121
void raise() const
Definition errorcode.h:603
erc()
Default ctor for erc objects creates an inactive error.
Definition errorcode.h:437
bool is_active() const
Return activity flag.
Definition errorcode.h:558
const errfac & facility() const
Return reference to facility.
Definition errorcode.h:563
erc & operator=(const erc &rhs)
Principal assignment operator.
Definition errorcode.h:512
level
Error levels (borrowed from BSD Unix)
Definition errorcode.h:77
@ emerg
always logged, thrown
Definition errorcode.h:85
@ none
always not logged, not thrown
Definition errorcode.h:78
@ notice
default not logged, not thrown
Definition errorcode.h:80
@ info
default not logged, not thrown
Definition errorcode.h:79
@ error
default logged, thrown
Definition errorcode.h:82
@ alert
default logged, thrown
Definition errorcode.h:84
@ critical
default logged, thrown
Definition errorcode.h:83
@ warning
default logged, not thrown
Definition errorcode.h:81
An error facility routes a group of errors handled in a similar manner.
Definition errorcode.h:141
virtual void raise(const erc &e) const
Check if error must be logged or thrown.
Definition errorcode.h:405
const std::string & name() const
get name
Definition errorcode.h:372
erc::level log_priority() const
get log priority
Definition errorcode.h:367
virtual void log(const erc &e) const
Definition errorcode.h:419
erc::level throw_priority() const
get throw priority
Definition errorcode.h:357
void log_priority(erc::level pri)
set log priority
Definition errorcode.h:362
static void Default(errfac *f)
set default facility
Definition errorcode.h:392
errfac(const std::string &name="Error")
Set defaults for log and throw levels.
Definition errorcode.h:346
static errfac & Default()
get default facility
Definition errorcode.h:383
void throw_priority(erc::level pri)
set throw priority
Definition errorcode.h:352
virtual std::string message(const erc &e) const
return message to be logged
Definition errorcode.h:378
Definition errorcode.h:183
errfac deffac
The default facility.
Definition errorcode.h:327
timeval operator*(const timeval &op1, int op2)
Multiplication by an integer.
Definition tvops.h:188