MLIB
Loading...
Searching...
No Matches
errorcode.h
Go to the documentation of this file.
1#pragma once
51
52#if __has_include("defs.h")
53#include "defs.h"
54#endif
55
56#include <string>
57
58#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) \
59 || (!defined(_MSVC_LANG) && (__cplusplus < 201703L))
60#error "errorcode requires c++17"
61#endif
62
63namespace mlib {
64
65class errfac;
66
67class erc
68{
69public:
82 erc ();
83 explicit erc (int value, level priority = level::error);
84 explicit erc (int value, const mlib::errfac& facility, level priority = level::error);
85 erc (const erc& other);
86 erc (erc&& other);
87
88 ~erc () noexcept (false);
89 erc& operator= (const erc& rhs);
90 erc& operator= (erc&& rhs);
91 operator int () const;
92
94 level priority () const;
95
97 bool is_active () const;
98
100 const errfac& facility () const;
101
102 bool operator== (const erc& other) const;
103 bool operator!= (const erc& other) const;
104
105 void raise () const;
106
107 void reactivate () const;
108 void deactivate () const;
109
110 int code () const;
111
113 std::string message () const;
114 void message (const std::string& m);
115
116 static erc success;
117
118private:
119 // bit fields
120 int value : 24;
121 int priority_ : 4;
122 mutable int active : 1;
123
124 const errfac& facility_;
125 std::string msg;
126
127 friend class errfac;
128};
129
134
136{
137public:
138 // constructors/destructor
139 errfac (const std::string& name = "Error");
140
142 void throw_priority (erc::level pri);
143
145 erc::level throw_priority () const;
146
148 void log_priority (erc::level pri);
149
151 erc::level log_priority () const;
152
154 virtual std::string message (const erc& e) const;
155
157 const std::string& name () const;
158
160 static void Default (errfac* f);
161
163 static errfac& Default ();
164
165 virtual void raise (const erc& e) const;
166 virtual void log (const erc& e) const;
167
168private:
169 erc::level log_level;
170 erc::level throw_level;
171 std::string name_;
172 static errfac* default_facility;
173};
174
175#if (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) \
176 || (!defined(_MSVC_LANG) && (__cplusplus >= 202002L))
177template <class T>
178concept checkable = !std::is_convertible_v<T, int>;
179
196template <checkable T>
197class checked : public erc
198{
199public:
202 checked ()
203 : erc ()
204 , obj ()
205 {}
206
208 checked (const T& obj_, const erc& err)
209 : erc (err)
210 , obj (obj_)
211 {}
212
214 checked (const T& obj_, int value = 0, erc::level pri_ = erc::level::error)
215 : erc (value, pri_)
216 , obj (obj_)
217 {}
218
219 checked (T&& obj_, erc&& err)
220 : erc (std::move (err))
221 , obj (std::move (obj_))
222 {}
223
224 checked (T&& obj_, const erc& err)
225 : erc (err)
226 , obj (std::move (obj_))
227 {}
228
230 checked (const checked<T>& other)
231 : erc (other)
232 , obj (other.obj)
233 {}
234
236 checked (checked<T>&& other)
237 : erc (other)
238 , obj (other.obj)
239 {}
240
241 ~checked () noexcept (false) = default;
242
244 checked<T>& operator= (const checked<T>& rhs)
245 {
246 if (&rhs != this)
247 {
248 erc::operator= (rhs);
249 obj = rhs.obj;
250 }
251 return *this;
252 }
253
255 checked<T>& operator= (checked<T>&& rhs)
256 {
257 if (&rhs != this)
258 {
259 *(erc*)this = std::move (rhs);
260 obj = std::move (rhs.obj);
261 }
262 return *this;
263 }
264
266 checked<T>& operator= (const erc& rhs)
267 {
268 erc::operator= (rhs);
269 return *this;
270 }
271
274 T& operator* ()
275 {
276 if (code () && priority ())
277 {
278 reactivate ();
279 raise ();
280 }
281 return obj;
282 }
283
284 const T& operator* () const
285 {
286 if (code () && priority ())
287 {
288 reactivate ();
289 raise ();
290 }
291 return obj;
292 }
293
294 T* operator->()
295 {
296 if (code () && priority ())
297 {
298 reactivate ();
299 raise ();
300 }
301 return &obj;
302 }
303 const T* operator->() const
304 {
305 if (code () && priority ())
306 {
307 reactivate ();
308 raise ();
309 }
310 return &obj;
311 }
313
314protected:
315 T obj;
316};
317#endif
318
319//----------------------- errfac inlines -------------------------------------
320
323
325inline errfac* errfac::default_facility = &deffac;
326
339
341inline errfac::errfac (const std::string& name)
342 : throw_level (erc::level::error)
343 , log_level (erc::level::warning)
344 , name_ (name)
345{}
346
348{
349 throw_level = (pri < erc::info) ? erc::info : (pri > erc::emerg) ? erc::emerg : pri;
350}
351
353{
354 return throw_level;
355}
356
358{
359 log_level = (pri < erc::info) ? erc::info : (pri > erc::emerg) ? erc::emerg : pri;
360}
361
363{
364 return log_level;
365}
366
367inline const std::string& errfac::name () const
368{
369 return name_;
370}
371
373inline std::string errfac::message (const erc& e) const
374{
375 return std::string ("error ") + std::to_string (e.value);
376}
377
379{
380 return *default_facility;
381}
382
387inline void errfac::Default (errfac* facility)
388{
389 default_facility = facility ? facility : &deffac;
390}
391
400inline void errfac::raise (const erc& e) const
401{
402 if (e.priority_ >= log_level)
403 log (e);
404 if (e.priority_ >= throw_level)
405 {
406 // Make sure this erc is not thrown again
407 e.active = 0;
408 throw e;
409 }
410}
411
414inline void errfac::log (const erc& e) const
415{
416 fprintf (stderr, "%s - %s\n", name ().c_str (), e.message ().c_str ());
417}
418
419//--------------------------- erc inlines -------------------------------------
420
430
432inline erc::erc ()
433 : value{0}
434 , priority_{none}
435 , active{false}
436 , facility_{errfac::Default ()}
437{}
438
440inline erc::erc (int v, level l)
441 : value{v}
442 , priority_{(unsigned short)l}
443 , facility_{errfac::Default ()}
444 , active{true}
445{}
446
448inline erc::erc (int v, const mlib::errfac& f, level l)
449 : value{v}
450 , priority_{(unsigned short)l}
451 , facility_{f}
452 , active{true}
453{}
454
467inline erc::erc (const erc& other)
468 : value{other.value}
469 , priority_{other.priority_}
470 , active{other.active}
471 , facility_{other.facility_}
472 , msg{other.msg}
473{
474 // we are the active error now, the other is deactivated
475 other.active = 0;
476}
477
479inline erc::erc (erc&& other)
480 : value{other.value}
481 , priority_{other.priority_}
482 , active{other.active}
483 , facility_{other.facility_}
484 , msg{other.msg}
485{
486 // we are the active error now, the other is deactivated
487 other.active = 0;
488}
489
491inline erc::~erc () noexcept (false)
492{
493 raise ();
494}
495
507inline erc& erc::operator= (const erc& rhs)
508{
509 if (&rhs != this)
510 {
511 int rhs_active = rhs.active;
512 rhs.active = 0; // prevent rhs from throwing if we throw
513 if (active && priority_)
514 facility_.raise (*this);
515 value = rhs.value;
516 priority_ = rhs.priority_;
517 const_cast<errfac&> (facility_) = rhs.facility_;
518 msg = rhs.msg;
519 active = rhs_active;
520 }
521 return *this;
522}
523
531inline erc& erc::operator= (erc&& rhs)
532{
533 if (&rhs != this)
534 {
535 bool rhs_active = rhs.active;
536 rhs.active = 0; // prevent rhs from throwing if we throw
537 if (active && value && priority_)
538 facility_.raise (*this);
539 value = rhs.value;
540 priority_ = rhs.priority_;
541 const_cast<errfac&>(facility_) = rhs.facility_;
542 msg = rhs.msg;
543 active = rhs_active;
544 }
545 return *this;
546}
547
549{
550 return (erc::level)priority_;
551}
552
553inline bool erc::is_active () const
554{
555 return active;
556}
557
558inline const errfac& erc::facility () const
559{
560 return facility_;
561}
562
571inline bool erc::operator== (const erc& other) const
572{
573 active = false;
574 const_cast<erc&> (other).active = false;
575 if ((!priority_ || !value) && (!other.priority_ || !other.value))
576 return true; // success values are the same
577 if (&facility_ == &other.facility_ && priority_ == other.priority_ && value == other.value)
578 return true;
579
580 return false;
581}
582
591inline bool erc::operator!= (const erc& other) const
592{
593 return !operator== (other);
594}
595
598inline void erc::raise () const
599{
600 if (value && active && priority_)
601 facility_.raise (*this);
602 }
603
610inline int erc::code () const
611{
612 return value;
613}
614
621inline std::string erc::message () const
622{
623 return msg.empty () ? facility_.message (*this) : msg;
624}
625
627inline void erc::message (const std::string& m)
628{
629 msg = m;
630}
631
637inline erc::operator int () const
638{
639 active = 0;
640 return value;
641}
642
644inline void erc::reactivate () const
645{
646 active = 1;
647}
648
654inline void erc::deactivate () const
655{
656 active = 0;
657}
658
660inline erc erc::success{0, erc::none};
661
662} // namespace mlib
objects returned as a function result or thrown directly.
Definition errorcode.h:68
void reactivate() const
Similar to re-throwing an exception.
Definition errorcode.h:644
bool operator!=(const erc &other) const
Inequality comparison operator.
Definition errorcode.h:591
int code() const
Return numerical value.
Definition errorcode.h:610
std::string message() const
Get logging message.
Definition errorcode.h:621
bool operator==(const erc &other) const
Equality comparison operator.
Definition errorcode.h:571
level priority() const
Return priority value.
Definition errorcode.h:548
~erc() noexcept(false)
Destructor. Call raise() function to see if the error should get logged or thrown.
Definition errorcode.h:491
void deactivate() const
Marks error code as inactive.
Definition errorcode.h:654
static erc success
The SUCCESS indicator.
Definition errorcode.h:116
void raise() const
Definition errorcode.h:598
erc()
Default ctor for erc objects creates an inactive error.
Definition errorcode.h:432
bool is_active() const
Return activity flag.
Definition errorcode.h:553
const errfac & facility() const
Return reference to facility.
Definition errorcode.h:558
erc & operator=(const erc &rhs)
Principal assignment operator.
Definition errorcode.h:507
level
Error levels (borrowed from BSD Unix)
Definition errorcode.h:72
@ emerg
always logged, thrown
Definition errorcode.h:80
@ none
always not logged, not thrown
Definition errorcode.h:73
@ notice
default not logged, not thrown
Definition errorcode.h:75
@ info
default not logged, not thrown
Definition errorcode.h:74
@ error
default logged, thrown
Definition errorcode.h:77
@ alert
default logged, thrown
Definition errorcode.h:79
@ critical
default logged, thrown
Definition errorcode.h:78
@ warning
default logged, not thrown
Definition errorcode.h:76
An error facility routes a group of errors handled in a similar manner.
Definition errorcode.h:136
virtual void raise(const erc &e) const
Check if error must be logged or thrown.
Definition errorcode.h:400
const std::string & name() const
get name
Definition errorcode.h:367
erc::level log_priority() const
get log priority
Definition errorcode.h:362
virtual void log(const erc &e) const
Definition errorcode.h:414
erc::level throw_priority() const
get throw priority
Definition errorcode.h:352
void log_priority(erc::level pri)
set log priority
Definition errorcode.h:357
static void Default(errfac *f)
set default facility
Definition errorcode.h:387
errfac(const std::string &name="Error")
Set defaults for log and throw levels.
Definition errorcode.h:341
static errfac & Default()
get default facility
Definition errorcode.h:378
void throw_priority(erc::level pri)
set throw priority
Definition errorcode.h:347
virtual std::string message(const erc &e) const
return message to be logged
Definition errorcode.h:373
errfac deffac
The default facility.
Definition errorcode.h:322
timeval operator*(const timeval &op1, int op2)
Multiplication by an integer.
Definition tvops.h:178