diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/eina/src/include/eina_safety_checks.h | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/libraries/eina/src/include/eina_safety_checks.h b/libraries/eina/src/include/eina_safety_checks.h new file mode 100644 index 0000000..4751e5f --- /dev/null +++ b/libraries/eina/src/include/eina_safety_checks.h | |||
@@ -0,0 +1,254 @@ | |||
1 | /* EINA - EFL data type library | ||
2 | * Copyright (C) 2008 Gustavo Sverzut Barbieri | ||
3 | * | ||
4 | * This library is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU Lesser General Public | ||
6 | * License as published by the Free Software Foundation; either | ||
7 | * version 2.1 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This library is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * Lesser General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Lesser General Public | ||
15 | * License along with this library; | ||
16 | * if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef EINA_SAFETY_CHECKS_H_ | ||
20 | #define EINA_SAFETY_CHECKS_H_ | ||
21 | |||
22 | /** | ||
23 | * @addtogroup Eina_Tools_Group Tools | ||
24 | * | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | /** | ||
29 | * @defgroup Eina_Safety_Checks_Group Safety Checks | ||
30 | * | ||
31 | * @warning @c eina_safety_checks.h should only be included by source | ||
32 | * files, after all other includes and before the source file | ||
33 | * specific includes. By source file specific includes we | ||
34 | * mean those that define the functions that are being | ||
35 | * checked. The reason for such complexity is the trick to | ||
36 | * avoid compiler optimizations. If compilers are told that | ||
37 | * some given function will never receive @c NULL | ||
38 | * (EINA_ARG_NONNULL(), then compiler will emit a warning if | ||
39 | * it detects so (good!) but will remove any checks for that | ||
40 | * condition as it believes it will never happen, removing | ||
41 | * all safety checks! By including @c eina_safety_checks.h it | ||
42 | * will redefine EINA_ARG_NONNULL() to void and compiler | ||
43 | * warning will not be emitted, but checks will be there. The | ||
44 | * files already processed with the old macro | ||
45 | * EINA_ARG_NONNULL() will still work and emit the warnings. | ||
46 | * | ||
47 | * | ||
48 | * @code | ||
49 | * | ||
50 | * // all these files will emit warning from EINA_ARG_NONNULL() | ||
51 | * #include <Evas.h> // third party headers | ||
52 | * #include <Ecore.h> | ||
53 | * #include <eina_error.h> // eina own header | ||
54 | * | ||
55 | * #include <eina_safety_checks.h> | ||
56 | * // all these files below will NOT emit warning from EINA_ARG_NONNULL(), | ||
57 | * // but this is required to have the functions defined there to be checked | ||
58 | * // for NULL pointers | ||
59 | * #include "my_functions1.h" | ||
60 | * #include "my_functions2.h" | ||
61 | * | ||
62 | * @endcode | ||
63 | */ | ||
64 | |||
65 | /** | ||
66 | * @addtogroup Eina_Safety_Checks_Group Safety Checks | ||
67 | * | ||
68 | * Safety checks are a set of macros to check for parameters or values | ||
69 | * that should never happen, it is similar in concept to assert(), but | ||
70 | * will log and return instead of abort() your program. | ||
71 | * | ||
72 | * Since these cases should never happen, one may wantto keep safety | ||
73 | * checks enabled during tests but disable then during deploy, not | ||
74 | * doing any checks at all. This is a common requirement for embedded | ||
75 | * systems. Whenever to check or not should be set during compile time | ||
76 | * by using @c --disable-safety-checks or @c --enable-safety-checks | ||
77 | * options to @c configure script. | ||
78 | * | ||
79 | * Whenever these macros capture an error, EINA_LOG_ERR() will be | ||
80 | * called and @c eina_error set to @c EINA_ERROR_SAFETY_FAILED and can | ||
81 | * be checked with eina_error_get() after call. | ||
82 | * | ||
83 | * @see EINA_SAFETY_ON_NULL_RETURN(), EINA_SAFETY_ON_NULL_RETURN_VAL() | ||
84 | * and other macros. | ||
85 | * | ||
86 | * @{ | ||
87 | */ | ||
88 | |||
89 | #include "eina_config.h" | ||
90 | #include "eina_error.h" | ||
91 | |||
92 | /** | ||
93 | * @var EINA_ERROR_SAFETY_FAILED | ||
94 | * Error identifier corresponding to safety check failure. | ||
95 | */ | ||
96 | EAPI extern Eina_Error EINA_ERROR_SAFETY_FAILED; | ||
97 | |||
98 | #ifdef EINA_SAFETY_CHECKS | ||
99 | |||
100 | #include "eina_log.h" | ||
101 | |||
102 | #define EINA_SAFETY_ON_NULL_RETURN(exp) \ | ||
103 | do \ | ||
104 | { \ | ||
105 | if (EINA_UNLIKELY((exp) == NULL)) \ | ||
106 | { \ | ||
107 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
108 | EINA_LOG_ERR("%s", "safety check failed: " # exp " == NULL"); \ | ||
109 | return; \ | ||
110 | } \ | ||
111 | } \ | ||
112 | while (0) | ||
113 | |||
114 | #define EINA_SAFETY_ON_NULL_RETURN_VAL(exp, val) \ | ||
115 | do \ | ||
116 | { \ | ||
117 | if (EINA_UNLIKELY((exp) == NULL)) \ | ||
118 | { \ | ||
119 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
120 | EINA_LOG_ERR("%s", "safety check failed: " # exp " == NULL"); \ | ||
121 | return (val); \ | ||
122 | } \ | ||
123 | } \ | ||
124 | while (0) | ||
125 | |||
126 | #define EINA_SAFETY_ON_NULL_GOTO(exp, label) \ | ||
127 | do \ | ||
128 | { \ | ||
129 | if (EINA_UNLIKELY((exp) == NULL)) \ | ||
130 | { \ | ||
131 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
132 | EINA_LOG_ERR("%s", "safety check failed: " # exp " == NULL"); \ | ||
133 | goto label; \ | ||
134 | } \ | ||
135 | } \ | ||
136 | while (0) | ||
137 | |||
138 | #define EINA_SAFETY_ON_TRUE_RETURN(exp) \ | ||
139 | do \ | ||
140 | { \ | ||
141 | if (EINA_UNLIKELY(exp)) \ | ||
142 | { \ | ||
143 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
144 | EINA_LOG_ERR("%s", "safety check failed: " # exp " is true"); \ | ||
145 | return; \ | ||
146 | } \ | ||
147 | } \ | ||
148 | while (0) | ||
149 | |||
150 | #define EINA_SAFETY_ON_TRUE_RETURN_VAL(exp, val) \ | ||
151 | do \ | ||
152 | { \ | ||
153 | if (EINA_UNLIKELY(exp)) \ | ||
154 | { \ | ||
155 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
156 | EINA_LOG_ERR("%s", "safety check failed: " # exp " is true"); \ | ||
157 | return val; \ | ||
158 | } \ | ||
159 | } \ | ||
160 | while (0) | ||
161 | |||
162 | #define EINA_SAFETY_ON_TRUE_GOTO(exp, label) \ | ||
163 | do \ | ||
164 | { \ | ||
165 | if (EINA_UNLIKELY(exp)) \ | ||
166 | { \ | ||
167 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
168 | EINA_LOG_ERR("%s", "safety check failed: " # exp " is true"); \ | ||
169 | goto label; \ | ||
170 | } \ | ||
171 | } \ | ||
172 | while (0) | ||
173 | |||
174 | #define EINA_SAFETY_ON_FALSE_RETURN(exp) \ | ||
175 | do \ | ||
176 | { \ | ||
177 | if (EINA_UNLIKELY(!(exp))) \ | ||
178 | { \ | ||
179 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
180 | EINA_LOG_ERR("%s", "safety check failed: " # exp " is false"); \ | ||
181 | return; \ | ||
182 | } \ | ||
183 | } \ | ||
184 | while (0) | ||
185 | |||
186 | #define EINA_SAFETY_ON_FALSE_RETURN_VAL(exp, val) \ | ||
187 | do \ | ||
188 | { \ | ||
189 | if (EINA_UNLIKELY(!(exp))) \ | ||
190 | { \ | ||
191 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
192 | EINA_LOG_ERR("%s", "safety check failed: " # exp " is false"); \ | ||
193 | return val; \ | ||
194 | } \ | ||
195 | } \ | ||
196 | while (0) | ||
197 | |||
198 | #define EINA_SAFETY_ON_FALSE_GOTO(exp, label) \ | ||
199 | do \ | ||
200 | { \ | ||
201 | if (EINA_UNLIKELY(!(exp))) \ | ||
202 | { \ | ||
203 | eina_error_set(EINA_ERROR_SAFETY_FAILED); \ | ||
204 | EINA_LOG_ERR("%s", "safety check failed: " # exp " is false"); \ | ||
205 | goto label; \ | ||
206 | } \ | ||
207 | } \ | ||
208 | while (0) | ||
209 | |||
210 | #ifdef EINA_ARG_NONNULL | ||
211 | /* make EINA_ARG_NONNULL void so GCC does not optimize safety checks */ | ||
212 | #undef EINA_ARG_NONNULL | ||
213 | #define EINA_ARG_NONNULL(idx, ...) | ||
214 | #endif | ||
215 | |||
216 | #else /* no safety checks */ | ||
217 | |||
218 | #define EINA_SAFETY_ON_NULL_RETURN(exp) \ | ||
219 | do { (void)(!(exp)); } while (0) | ||
220 | |||
221 | #define EINA_SAFETY_ON_NULL_RETURN_VAL(exp, val) \ | ||
222 | do { if (0 && !(exp)) { (void)val; } } while (0) | ||
223 | |||
224 | #define EINA_SAFETY_ON_NULL_GOTO(exp, label) \ | ||
225 | do { if (0 && (exp) == NULL) { goto label; } } while (0) | ||
226 | |||
227 | #define EINA_SAFETY_ON_TRUE_RETURN(exp) \ | ||
228 | do { (void)(exp); } while (0) | ||
229 | |||
230 | #define EINA_SAFETY_ON_TRUE_RETURN_VAL(exp, val) \ | ||
231 | do { if (0 && (exp)) { (void)val; } } while (0) | ||
232 | |||
233 | #define EINA_SAFETY_ON_TRUE_GOTO(exp, label) \ | ||
234 | do { if (0 && (exp)) { goto label; } } while (0) | ||
235 | |||
236 | #define EINA_SAFETY_ON_FALSE_RETURN(exp) \ | ||
237 | do { (void)(!(exp)); } while (0) | ||
238 | |||
239 | #define EINA_SAFETY_ON_FALSE_RETURN_VAL(exp, val) \ | ||
240 | do { if (0 && !(exp)) { (void)val; } } while (0) | ||
241 | |||
242 | #define EINA_SAFETY_ON_FALSE_GOTO(exp, label) \ | ||
243 | do { if (0 && !(exp)) { goto label; } } while (0) | ||
244 | |||
245 | #endif /* safety checks macros */ | ||
246 | #endif /* EINA_SAFETY_CHECKS_H_ */ | ||
247 | |||
248 | /** | ||
249 | * @} | ||
250 | */ | ||
251 | |||
252 | /** | ||
253 | * @} | ||
254 | */ | ||