aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/include/eina_magic.h
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src/include/eina_magic.h')
-rw-r--r--libraries/eina/src/include/eina_magic.h330
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 */
135typedef 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 */
156EAPI 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 */
172EAPI 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 */
191EAPI 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 */
208EAPI 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 */
299EAPI 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_ */