EFL 1.7 svn doobies
[profile/ivi/eina.git] / src / include / eina_magic.h
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.
236  * Use #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_ */