-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbien_assert.h
More file actions
150 lines (133 loc) · 6.56 KB
/
bien_assert.h
File metadata and controls
150 lines (133 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma once
// Copyright David Lawrence Bien 1997 - 2021.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt).
// bien_assert.h
#include <assert.h>
#include <string>
#include "syslogmgr.h"
#include "_namdexc.h"
// This file defines assertion and runtime check stuff.
// We allow assertion when ASSERTSENABLED is set non-zero. Normal in release binaries this is not set.
// Runtime checks are always enabled as the code is expect to *need* to run - i.e. the running
// of code inside of a runtime check is not optional.
__BIENUTIL_BEGIN_NAMESPACE
#ifdef Assert
#error bien_assert.h: Assert() macro is already defined.
#endif
enum EAbortBreakIgnore
{
eabiIgnore, // Ignore entirely - log and continue.
eabiBreak, // Break into the debugger but otherwise same as Ignore.
eabiThrowException, // Throw an exception after logging - this is not valid for Assert() because it changes the flow of control - thought I guess it could be used for unit testing.
eabiAbort, // Abort after logging.
eabiEAbortBreakIgnoreCount
};
// This exception will get thrown when eabiThrowException is set.
class VerifyFailedException : public _t__Named_exception< >
{
typedef VerifyFailedException _TyThis;
typedef _t__Named_exception<> _TyBase;
public:
VerifyFailedException( const char * _pc )
: _TyBase( _pc )
{
}
VerifyFailedException( const string_type & __s )
: _TyBase( __s )
{
}
VerifyFailedException( const char * _pcFmt, va_list _args )
: _TyBase( _pcFmt, _args )
{
}
};
// By default we will always add the __FILE__, __LINE__ even in retail for debugging purposes.
#define THROWVERIFYFAILEDEXCEPTION( MESG, ... ) ExceptionUsage<VerifyFailedException>::ThrowFileLine( __FILE__, __LINE__, MESG, ##__VA_ARGS__ )
#ifndef ASSERTSENABLED
#ifdef NDEBUG
#define ASSERTSENABLED 0
#else
#define ASSERTSENABLED 1
#endif // !NDEBUG
#endif // !ASSERTSENABLED
// We might have assert-related statements - i.e. when we record some initial state and then assert something about it later.
// In those case we need to have these previous assert-related statements (or subsequent for that matter) present in the build regardless of NDEBUG value.
#if ASSERTSENABLED
#define AssertStatement( s ) s;
#else
#define AssertStatement( s )
#endif
#if ASSERTSENABLED
#define AssertFragment( s ) s
#else
#define AssertFragment( s )
#endif
#if ASSERTSENABLED
#define AssertComma( s ) ,s
#else
#define AssertComma( s )
#endif
#if ASSERTSENABLED
#define AssertComma2( s1, s2 ) s1##,##s2
#else
#define AssertComma2( s )
#endif
#ifndef ACTIONONASSERT
// By default we do not abort on assert. Abort generates a core dump so if you want to examine the state of things you would want to abort.
#define ACTIONONASSERT __BIENUTIL_USE_NAMESPACE::eabiBreak
#endif // !ACTIONONASSERT
#ifndef ACTIONONVERIFY
// By default we do not abort on VERIFY. Abort generates a core dump so if you want to examine the state of things you would want to abort.
#define ACTIONONVERIFY __BIENUTIL_USE_NAMESPACE::eabiBreak
#endif // !ACTIONONVERIFY
// This failure mimicks the ANSI standard failure: Print a message (in our case to the syslog and potentially as well to the screen) and then flush the log file and abort() (if _fAbort).
// Need to define this later so we can use Assert() in various objects that we'd like to.
void
AssertVerify_LogMessage( EAbortBreakIgnore _eabi, bool _fAssert, const char * _szAssertVerify, const char * _szAssertion, const char * _szFile,
unsigned int _nLine, const char * _szFunction, const char * _szMesg, ... );
// Verify() macros that by default will break into the debugger.
#define Verify(expr) \
( static_cast <bool> (expr) \
? void (0) \
: AssertVerify_LogMessage( ACTIONONVERIFY, false, "Verify", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, 0 ) )
#define VerifySz(expr, sz, ...) \
( static_cast <bool> (expr) \
? void (0) \
: AssertVerify_LogMessage( ACTIONONVERIFY, false, "Verify", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, sz, ##__VA_ARGS__ ) )
// FVerifyInline(expr) expects expr to be true and will assert if not but returns the result of the operation to the caller and thus
// may be used inline (and indeed is intended to be used inline) in a logical statement.
#define FVerifyInline(expr) \
( static_cast <bool> (expr) \
? true \
: ( AssertVerify_LogMessage( ACTIONONVERIFY, false, "FVerifyInline", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, 0 ), false ) )
// Verify() macros that will throw an exception even in retail.
#define VerifyThrow(expr) \
( static_cast <bool> (expr) \
? void (0) \
: AssertVerify_LogMessage( eabiThrowException, false, "VerifyThrow", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, 0 ) )
#define VerifyThrowSz(expr, sz, ...) \
( static_cast <bool> (expr) \
? void (0) \
: AssertVerify_LogMessage( eabiThrowException, false, "VerifyThrow", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, sz, ##__VA_ARGS__ ) )
// FVerifyInline(expr) expects expr to be true and will assert if not but returns the result of the operation to the caller and thus
// may be used inline (and indeed is intended to be used inline) in a logical statement.
#define FVerifyThrowInline(expr) \
( static_cast <bool> (expr) \
? true \
: ( AssertVerify_LogMessage( eabiThrowException, false, "FVerifyThrowInline", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, 0 ), false ) )
#if !ASSERTSENABLED
#define Assert(expr) (static_cast<void>(0))
#define AssertSz(expr, sz, ...) (static_cast<void>(0))
#else // #if !ASSERTSENABLED
#define Assert(expr) \
( static_cast <bool> (expr) \
? void (0) \
: AssertVerify_LogMessage( ACTIONONASSERT, true, "Assert", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, 0 ) )
#define AssertSz(expr, sz, ...) \
( static_cast <bool> (expr) \
? void (0) \
: AssertVerify_LogMessage( ACTIONONASSERT, true, "Assert", #expr, __FILE__, __LINE__, FUNCTION_PRETTY_NAME, sz, ##__VA_ARGS__ ) )
#endif // #if !ASSERTSENABLED
__BIENUTIL_END_NAMESPACE