1 #ifndef R_ASSERT_H
2 #define R_ASSERT_H
3 
4 #include "r_log.h"
5 
6 #define R_STATIC_ASSERT(x)\
7 	switch (0) {\
8 	case 0:\
9 	case (x):;\
10 	}
11 
12 R_API void r_assert_log(RLogLevel level, const char *fmt, ...) R_PRINTF_CHECK(2, 3);
13 
14 #if defined (__GNUC__) && defined (__cplusplus)
15 #define R_FUNCTION ((const char*) (__PRETTY_FUNCTION__))
16 #elif defined(__STDC__) && defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
17 #define R_FUNCTION ((const char*) (__func__))
18 #elif defined (__GNUC__) || (defined(_MSC_VER) && (_MSC_VER > 1300))
19 #define R_FUNCTION ((const char*) (__FUNCTION__))
20 #else
21 #warning Do not know how to get function name in this setup
22 #define R_FUNCTION ((const char*) ("???"))
23 #endif
24 
25 #define r_warn_if_reached() \
26 	do { \
27 		r_assert_log (R_LOGLVL_WARN, "(%s:%d):%s%s code should not be reached\n", \
28 			__FILE__, __LINE__, R_FUNCTION, R_FUNCTION[0] ? ":" : ""); \
29 	} while (0)
30 
31 #define r_warn_if_fail(expr) \
32 	do { \
33 		if (!(expr)) { \
34 			r_assert_log (R_LOGLVL_WARN, "WARNING (%s:%d):%s%s runtime check failed: (%s)\n", \
35 				__FILE__, __LINE__, R_FUNCTION, R_FUNCTION[0] ? ":" : "", #expr); \
36 		} \
37 	} while (0)
38 
39 /*
40  * R_CHECKS_LEVEL determines the behaviour of the r_return_* set of functions.
41  *
42  * 0: completely disable every function and make them like no-operation
43  * 1: silently enable checks. Check expressions and do return, but do not log anything
44  * 2: enable checks and logging (DEFAULT)
45  * 3: transform them into real assertion
46  */
47 #ifndef R_CHECKS_LEVEL
48 #define R_CHECKS_LEVEL 2
49 #endif
50 
51 #if R_CHECKS_LEVEL == 0
52 
53 #define r_return_if_fail(expr) do { ; } while(0)
54 #define r_return_val_if_fail(expr, val) do { ; } while(0)
55 #define r_return_if_reached() do { ; } while(0)
56 #define r_return_val_if_reached(val) do { ; } while(0)
57 
58 #elif R_CHECKS_LEVEL == 1 || R_CHECKS_LEVEL == 2 // R_CHECKS_LEVEL
59 
60 #if R_CHECKS_LEVEL == 1
61 #define H_LOG_(loglevel, fmt, ...)
62 #else
63 #define H_LOG_(loglevel, fmt, ...) r_assert_log (loglevel, fmt, __VA_ARGS__)
64 #endif
65 
66 /**
67  * r_return_if_fail:
68  * @expr: the expression to check
69  *
70  * Verifies that the expression @expr, usually representing a precondition,
71  * evaluates to `true`. If the function returns a value, use
72  * r_return_val_if_fail() instead.
73  *
74  * If @expr evaluates to %FALSE, the current function should be considered to
75  * have undefined behaviour (a programmer error). The only correct solution
76  * to such an error is to change the module that is calling the current
77  * function, so that it avoids this incorrect call.
78  *
79  * To make this undefined behaviour visible, if @expr evaluates to %FALSE,
80  * the result is usually that a critical message is logged and the current
81  * function returns.
82  *
83  */
84 #define r_return_if_fail(expr) \
85 	do { \
86 		if (!(expr)) { \
87 			H_LOG_ (R_LOGLVL_WARN, "%s: assertion '%s' failed (line %d)\n", R_FUNCTION, #expr, __LINE__); \
88 			return; \
89 		} \
90 	} while (0)
91 
92 #define r_return_val_if_fail(expr, val) \
93 	do { \
94 		if (!(expr)) { \
95 			H_LOG_ (R_LOGLVL_WARN, "%s: assertion '%s' failed (line %d)\n", R_FUNCTION, #expr, __LINE__); \
96 			return (val); \
97 		} \
98 	} while (0)
99 
100 #define r_return_if_reached() \
101 	do { \
102 		H_LOG_ (R_LOGLVL_ERROR, "file %s: line %d (%s): should not be reached\n", __FILE__, __LINE__, R_FUNCTION); \
103 		return; \
104 	} while (0)
105 
106 #define r_return_val_if_reached(val) \
107 	do { \
108 		H_LOG_ (R_LOGLVL_ERROR, "file %s: line %d (%s): should not be reached\n", __FILE__, __LINE__, R_FUNCTION); \
109 		return (val); \
110 	} while (0)
111 
112 #else // R_CHECKS_LEVEL
113 
114 #include <assert.h>
115 
116 #define r_return_if_fail(expr) do { assert (expr); } while(0)
117 #define r_return_val_if_fail(expr, val) do { assert (expr); } while(0)
118 #define r_return_if_reached() do { assert (false); } while(0)
119 #define r_return_val_if_reached(val) do { assert (false); } while(0)
120 
121 #endif // R_CHECKS_LEVEL
122 
123 #endif
124