diff options
Diffstat (limited to 'libraries/eina/src/include/eina_magic.h')
-rw-r--r-- | libraries/eina/src/include/eina_magic.h | 330 |
1 files changed, 0 insertions, 330 deletions
diff --git a/libraries/eina/src/include/eina_magic.h b/libraries/eina/src/include/eina_magic.h deleted file mode 100644 index d4909d8..0000000 --- a/libraries/eina/src/include/eina_magic.h +++ /dev/null | |||
@@ -1,330 +0,0 @@ | |||
1 | /* EINA - EFL data type library | ||
2 | * Copyright (C) 2008 Cedric Bail | ||
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_MAGIC_H_ | ||
20 | #define EINA_MAGIC_H_ | ||
21 | |||
22 | #include "eina_config.h" | ||
23 | #include "eina_types.h" | ||
24 | #include "eina_error.h" | ||
25 | |||
26 | /** | ||
27 | * @page eina_magic_example_01_page | ||
28 | * @dontinclude eina_magic_01.c | ||
29 | * | ||
30 | * Whenever using Eina we must include it: | ||
31 | * @skipline #include | ||
32 | * | ||
33 | * For this example we are going to define two classes, person and pilot, and | ||
34 | * since every pilot is a person we use inheritance. To be type safe we are | ||
35 | * going to add EINA_MAGIC to our classes: | ||
36 | * @until struct _pilot pilot | ||
37 | * @note The values of BASETYPE_MAGIC and SUBTYPE_MAGIC have no meaning, the | ||
38 | * only important thing about them is that they be unique. | ||
39 | * | ||
40 | * Here we have a function to create a perso given a name, nothing too fancy: | ||
41 | * @until } | ||
42 | * | ||
43 | * And now the counterpart, a function the free a person. | ||
44 | * @until { | ||
45 | * Before we start releasing resources we check that the pointer we were given | ||
46 | * actually points to a person, and if not we will print an error message and | ||
47 | * quit: | ||
48 | * @until } | ||
49 | * @note EINA_MAGIC_FAIL is a macro that make's it easy to print an appropriate | ||
50 | * (and consistent) error message. | ||
51 | * Now knowing that ptr is indeed of type person we prooced to set EINA_MAGIC to | ||
52 | * EINA_MAGIC_NONE and free alocated memory: | ||
53 | * @until } | ||
54 | * @note Setting EINA_MAGIC to EINA_MAGIC_NONE is important to prevent the | ||
55 | * struct from being used after freed. | ||
56 | * | ||
57 | * Now we have our function to create a pilot, this one is a little more complex | ||
58 | * because we need to set EINA_MAGIC for the pilot and pilot->base, this is very | ||
59 | * important so that checking the EINA_MAGIC of (person*)my_pilot will work: | ||
60 | * @until } | ||
61 | * | ||
62 | * The function to free a pilot is not too different from the one that frees a | ||
63 | * person: | ||
64 | * @until } | ||
65 | * @until } | ||
66 | * | ||
67 | * We also create functions to print a person or a pilot that check the type of | ||
68 | * the pointers they receive: | ||
69 | * @until } | ||
70 | * @until } | ||
71 | * | ||
72 | * And on to our main function where we declare some variables and initialize | ||
73 | * Eina: | ||
74 | * @until eina_init | ||
75 | * | ||
76 | * For Eina to be able to provide more informative error messages we are going | ||
77 | * to give names to our EINA_MAGIC types: | ||
78 | * @until string_set | ||
79 | * | ||
80 | * Since our types won't live longer than the scope of the current function we | ||
81 | * can set the name without eina making a copy of the string: | ||
82 | * @until static_set | ||
83 | * | ||
84 | * Now we create a person, a pilot and print both as persons: | ||
85 | * @until person * | ||
86 | * | ||
87 | * Now we try to print both as pilots, which will obvisouly not work since base | ||
88 | * is not a pilot: | ||
89 | * @until pilot(sub | ||
90 | * | ||
91 | * That's all folks: | ||
92 | * @until } | ||
93 | * | ||
94 | * See full source @ref eina_magic_example_01_c "here". | ||
95 | */ | ||
96 | /** | ||
97 | * @page eina_magic_example_01_c Eina_Magic | ||
98 | * @include eina_magic_01.c | ||
99 | * @example eina_magic_01.c | ||
100 | */ | ||
101 | /** | ||
102 | * @addtogroup Eina_Tools_Group Tools | ||
103 | * | ||
104 | * @{ | ||
105 | */ | ||
106 | /** | ||
107 | * @defgroup Eina_Magic_Group Magic | ||
108 | * | ||
109 | * @brief Eina_Magic provides run-time type-checking. | ||
110 | * | ||
111 | * C is a weak statically typed language, in other words, it will just check for | ||
112 | * types during compile time and any cast will make the compiler believe the | ||
113 | * type is correct. | ||
114 | * | ||
115 | * In real world code we often need to deal with casts, either explicit or | ||
116 | * implicit by means of @c void*. We also need to resort to casts when doing | ||
117 | * inheritance in C. | ||
118 | * | ||
119 | * Eina_Magic give us a way to do casts and still be certain of the type we are | ||
120 | * opearting on. | ||
121 | * | ||
122 | * @note It should be noted that it is considered good practice to @b disable | ||
123 | * Eina_Magic for production code. The reasoning is that any Eina_Magic errors | ||
124 | * should have been caught during testing and therefore there is no reason to | ||
125 | * incur the performance downside of Eina_Magic. | ||
126 | * | ||
127 | * An @ref eina_magic_example_01_page "example" should elucidate matters. | ||
128 | * | ||
129 | * @{ | ||
130 | */ | ||
131 | |||
132 | /** | ||
133 | * An abstract type for a magic number. | ||
134 | */ | ||
135 | typedef unsigned int Eina_Magic; | ||
136 | |||
137 | /** | ||
138 | * @brief Return the string associated to the given magic identifier. | ||
139 | * | ||
140 | * @param magic The magic identifier. | ||
141 | * @return The string associated to the identifier. | ||
142 | * | ||
143 | * This function returns the string associated to @p magic. Even if none are | ||
144 | * found this function still returns non @c NULL, in this case an identifier | ||
145 | * such as "(none)", "(undefined)" or "(unknown)". | ||
146 | * | ||
147 | * The following identifiers may be returned whenever magic is | ||
148 | * invalid, with their meanings: | ||
149 | * | ||
150 | * - (none): no magic was registered exists at all. | ||
151 | * - (undefined): magic was registered and found, but no string associated. | ||
152 | * - (unknown): magic was not found in the registry. | ||
153 | * | ||
154 | * @warning The returned value must not be freed. | ||
155 | */ | ||
156 | EAPI const char *eina_magic_string_get(Eina_Magic magic) EINA_WARN_UNUSED_RESULT; | ||
157 | /** | ||
158 | * @brief Set the string associated to the given magic identifier. | ||
159 | * | ||
160 | * @param magic The magic identifier. | ||
161 | * @param magic_name The string associated to the identifier, must not | ||
162 | * be @c NULL. | ||
163 | * | ||
164 | * @return #EINA_TRUE on success, #EINA_FALSE on failure. | ||
165 | * | ||
166 | * This function sets the string @p magic_name to @p magic. It is not | ||
167 | * checked if number or string are already set, in which case you will end with | ||
168 | * duplicates. Internally, eina will make a copy of @p magic_name. | ||
169 | * | ||
170 | * @see eina_magic_string_static_set() | ||
171 | */ | ||
172 | EAPI Eina_Bool eina_magic_string_set(Eina_Magic magic, | ||
173 | const char *magic_name) EINA_ARG_NONNULL(2); | ||
174 | |||
175 | /** | ||
176 | * @brief Set the string associated to the given magic identifier. | ||
177 | * | ||
178 | * @param magic The magic identifier. | ||
179 | * @param magic_name The string associated to the identifier, must not be | ||
180 | * @c NULL. | ||
181 | * | ||
182 | * @return #EINA_TRUE on success, #EINA_FALSE on failure. | ||
183 | * | ||
184 | * This function sets the string @p magic_name to @p magic. It is not checked if | ||
185 | * number or string are already set, in which case you might end with | ||
186 | * duplicates. Eina will @b not make a copy of @p magic_name, this means that | ||
187 | * @p magic_name has to be a valid pointer for as long as @p magic is used. | ||
188 | * | ||
189 | * @see eina_magic_string_set() | ||
190 | */ | ||
191 | EAPI Eina_Bool eina_magic_string_static_set(Eina_Magic magic, | ||
192 | const char *magic_name) EINA_ARG_NONNULL(2); | ||
193 | |||
194 | /** | ||
195 | * @def EINA_MAGIC_NONE | ||
196 | * Random value for specifying that a structure using the magic | ||
197 | * feature has already been freed. It is used by eina_magic_fail(). | ||
198 | * | ||
199 | * If the magic feature of Eina is disabled, #EINA_MAGIC_NONE is just | ||
200 | * @c 0. | ||
201 | */ | ||
202 | #define EINA_MAGIC_NONE 0x1234fedc | ||
203 | |||
204 | /** | ||
205 | * @var EINA_ERROR_MAGIC_FAILED | ||
206 | * Error identifier corresponding to magic check failure. | ||
207 | */ | ||
208 | EAPI extern Eina_Error EINA_ERROR_MAGIC_FAILED; | ||
209 | |||
210 | |||
211 | #ifdef EINA_MAGIC_DEBUG | ||
212 | |||
213 | /** | ||
214 | * @def EINA_MAGIC | ||
215 | * Declaration of a variable of type #Eina_Magic. To put in a structure | ||
216 | * when one wants to use the magic feature of Eina with the functions | ||
217 | * of that structure, like that: | ||
218 | * | ||
219 | * @code | ||
220 | * struct Foo | ||
221 | * { | ||
222 | * int i; | ||
223 | * | ||
224 | * EINA_MAGIC | ||
225 | * }; | ||
226 | * @endcode | ||
227 | * | ||
228 | * If the magic feature of Eina is disabled, #EINA_MAGIC does nothing. | ||
229 | */ | ||
230 | #define EINA_MAGIC Eina_Magic __magic; | ||
231 | |||
232 | /** | ||
233 | * @def EINA_MAGIC_SET(d, m) | ||
234 | * Set the magic number of @p d to @p m. @p d must be a valid pointer | ||
235 | * to a structure holding an Eina magic number declaration. Use | ||
236 | * #EINA_MAGIC to add such declaration. | ||
237 | * | ||
238 | * If the magic feature of Eina is disabled, #EINA_MAGIC_CHECK is just | ||
239 | * the value @c 0. | ||
240 | */ | ||
241 | #define EINA_MAGIC_SET(d, m) (d)->__magic = (m) | ||
242 | |||
243 | /** | ||
244 | * @def EINA_MAGIC_CHECK(d, m) | ||
245 | * Test if @p d is @c NULL or not, and if not @c NULL, if | ||
246 | * @p d->__eina_magic is equal to @p m. @p d must be a structure that | ||
247 | * holds an Eina magic number declaration. Use #EINA_MAGIC to add such | ||
248 | * declaration. | ||
249 | * | ||
250 | * If the magic feature of Eina is disabled, #EINA_MAGIC_CHECK is just | ||
251 | * the value @c 1. | ||
252 | */ | ||
253 | #define EINA_MAGIC_CHECK(d, m) ((d) && ((d)->__magic == (m))) | ||
254 | |||
255 | /** | ||
256 | * @def EINA_MAGIC_FAIL(d, m) | ||
257 | * Call eina_magic_fail() with the parameters @p d, @p d->__magic, @p | ||
258 | * m, __FILE__, __FUNCTION__ and __LINE__. @p d must be a structure that | ||
259 | * holds an Eina magic number declaration. Use #EINA_MAGIC to add such | ||
260 | * declaration. | ||
261 | * | ||
262 | * If the magic feature of Eina is disabled, #EINA_MAGIC_FAIL does | ||
263 | * nothing. | ||
264 | */ | ||
265 | #define EINA_MAGIC_FAIL(d, m) \ | ||
266 | eina_magic_fail((void *)(d), \ | ||
267 | (d) ? (d)->__magic : 0, \ | ||
268 | (m), \ | ||
269 | __FILE__, \ | ||
270 | __FUNCTION__, \ | ||
271 | __LINE__); | ||
272 | |||
273 | /** | ||
274 | * @brief Display a message or abort if a magic check failed. | ||
275 | * | ||
276 | * @param d The checked data pointer. | ||
277 | * @param m The magic identifer to check. | ||
278 | * @param req_m The requested magic identifier to check. | ||
279 | * @param file The file in which the magic check failed. | ||
280 | * @param fnc The function in which the magic check failed. | ||
281 | * @param line The line at which the magic check failed. | ||
282 | * | ||
283 | * @warning You should @b strongly consider using @ref EINA_MAGIC_FAIL(d, m) | ||
284 | * instead. | ||
285 | * | ||
286 | * This function displays an error message if a magic check has | ||
287 | * failed, using the following logic in the following order: | ||
288 | * @li If @p d is @c NULL, a message warns about a @c NULL pointer. | ||
289 | * @li Otherwise, if @p m is equal to #EINA_MAGIC_NONE, a message | ||
290 | * warns about a handle that was already freed. | ||
291 | * @li Otherwise, if @p m is equal to @p req_m, a message warns about | ||
292 | * a handle that is of wrong type. | ||
293 | * @li Otherwise, a message warns you about ab-using that function... | ||
294 | * | ||
295 | * If the environment variable EINA_LOG_ABORT is set, abort() is | ||
296 | * called and the program stops. It is useful for debugging programs | ||
297 | * with gdb. | ||
298 | */ | ||
299 | EAPI void eina_magic_fail(void *d, Eina_Magic m, Eina_Magic req_m, | ||
300 | const char *file, const char *fnc, | ||
301 | int line) EINA_ARG_NONNULL(4, 5); | ||
302 | |||
303 | #else | ||
304 | |||
305 | /** | ||
306 | * @cond LOCAL | ||
307 | */ | ||
308 | |||
309 | #define EINA_MAGIC | ||
310 | #define EINA_MAGIC_SET(d, m) ((void)0) | ||
311 | #define EINA_MAGIC_CHECK(d, m) (1) | ||
312 | #define EINA_MAGIC_FAIL(d, m) ((void)0) | ||
313 | |||
314 | #define eina_magic_fail(d, m, req_m, file, fnx, line) ((void)0) | ||
315 | |||
316 | /** | ||
317 | * @endcond | ||
318 | */ | ||
319 | |||
320 | #endif | ||
321 | |||
322 | /** | ||
323 | * @} | ||
324 | */ | ||
325 | |||
326 | /** | ||
327 | * @} | ||
328 | */ | ||
329 | |||
330 | #endif /* EINA_MAGIC_H_ */ | ||