Wireshark
4.7.0
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
wsutil
ws_assert.h
Go to the documentation of this file.
1
10
#ifndef __WS_ASSERT_H__
11
#define __WS_ASSERT_H__
12
13
#include <ws_symbol_export.h>
14
#include <ws_attributes.h>
15
#include <stdbool.h>
16
#include <string.h>
17
#include <
wsutil/wslog.h
>
18
#include <
wsutil/wmem/wmem.h
>
19
20
/*
21
* XXX - WS_ASSERT_ENABLED is tested in various if statements
22
* below, so that we don't test various assertions unless
23
* assertions are enabled. Compilers will often partially
24
* evaluate (CONSTANT && (expression)) at compile time, so
25
* that if CONSTANT is 0 the rest of the test isn't evaluated
26
* and assumed to result in a false result, with the code in
27
* the if branch being removed, and if CONSTANT is 1, the
28
* code is treated as an if that tests the expression.
29
*
30
* This could mean that, if "defined but not used" tests are
31
* being done, any variable tested in the expression may be warned
32
* as "defined but not used" if WS_ASSERT_ENABLED is 0, causing
33
* a pile of warnings if the variable isn't marked as unused
34
* (especially true of parametre variables).
35
*
36
* However, some compilers - Clang, in my tests, and probably GCC,
37
* due to tests in builds not failing - treat "if (0 && (expression))"
38
* specially, pretending hat all variables in the expression are used,
39
* even if they aren't used in the generated code. (At least in
40
* Apple clang version 15.0.0 (clang-1500.1.0.2.5), it must be
41
* exactly 0 - (0) doesn't have the same effect.)
42
*
43
* That's all very well, but, unfortunately Microsoft Visual Studio's
44
* C compiler doesn't do that, so the variables have to be marked as
45
* unused, which may cause warnings "used, but marked as unused"
46
* warnings if the code is compiled with assertions enabled.
47
*/
48
#if defined(ENABLE_ASSERT)
49
#define WS_ASSERT_ENABLED 1
50
#elif defined(NDEBUG)
51
#define WS_ASSERT_ENABLED 0
52
#else
53
#define WS_ASSERT_ENABLED 1
54
#endif
55
56
#ifdef __cplusplus
57
extern
"C"
{
58
#endif
/* __cplusplus */
59
73
#define ws_assert_if_active(active, expr) \
74
do { \
75
if ((active) && !(expr)) \
76
ws_error("assertion failed: %s", #expr); \
77
} while (0)
78
89
#define ws_abort_if_fail(expr) \
90
ws_assert_if_active(true, expr)
91
102
#define ws_assert(expr) \
103
ws_assert_if_active(WS_ASSERT_ENABLED, expr)
104
105
116
#define ws_assert_streq(s1, s2) \
117
ws_assert((s1) && (s2) && strcmp((s1), (s2)) == 0)
118
130
#define ws_assert_utf8(str, len) \
131
do { \
132
const char *__assert_endptr; \
133
if (WS_ASSERT_ENABLED && \
134
!g_utf8_validate(str, len, &__assert_endptr)) { \
135
ws_log_utf8_full(LOG_DOMAIN_UTF_8, LOG_LEVEL_ERROR, \
136
__FILE__, __LINE__, __func__, \
137
str, len, __assert_endptr); \
138
} \
139
} while (0)
140
141
/*
142
* We don't want to disable ws_assert_not_reached() with (optional) assertions
143
* disabled.
144
* That would blast compiler warnings everywhere for no benefit, not
145
* even a miniscule performance gain. Reaching this function is always
146
* a programming error and will unconditionally abort execution.
147
*
148
* Note: With g_assert_not_reached() if the compiler supports unreachable
149
* built-ins (which recent versions of GCC and MSVC do) there is no warning
150
* blast with g_assert_not_reached() and G_DISABLE_ASSERT. However if that
151
* is not the case then g_assert_not_reached() is simply (void)0 and that
152
* causes the spurious warnings, because the compiler can't tell anymore
153
* that a certain code path is not used. We avoid that with
154
* ws_assert_not_reached(). There is no reason to ever use a no-op here.
155
*/
156
166
#define ws_assert_not_reached() \
167
ws_error("assertion \"not reached\" failed")
168
169
/*
170
* These macros can be used as an alternative to ws_assert() to
171
* assert some condition on function arguments. This must only be used
172
* to catch programming errors, in situations where an assertion is
173
* appropriate. And it should only be used if failing the condition
174
* doesn't necessarily lead to an inconsistent state for the program.
175
*
176
* It is possible to set the fatal log domain to "InvalidArg" to abort
177
* execution for debugging purposes, if one of these checks fail.
178
*/
179
191
#define ws_warn_badarg(str) \
192
ws_log_full(LOG_DOMAIN_EINVAL, LOG_LEVEL_WARNING, \
193
__FILE__, __LINE__, __func__, \
194
"invalid argument: %s", str)
195
207
#define ws_return_str_if(expr, scope) \
208
do { \
209
if (WS_ASSERT_ENABLED && (expr)) { \
210
ws_warn_badarg(#expr); \
211
return wmem_strdup_printf(scope, "(invalid argument: %s)", #expr); \
212
} \
213
} while (0)
214
225
#define ws_return_val_if(expr, val) \
226
do { \
227
if (WS_ASSERT_ENABLED && (expr)) { \
228
ws_warn_badarg(#expr); \
229
return (val); \
230
} \
231
} while (0)
232
233
#ifdef __cplusplus
234
}
235
#endif
/* __cplusplus */
236
237
#endif
/* __WS_ASSERT_H__ */
wmem.h
wslog.h
Generated by
1.9.8