bd7f58384bc7727d6f2aeb38da2e5ddc04e6979e
[profile/ivi/eina.git] / src / lib / eina_magic.c
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 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #ifdef HAVE_EVIL
27 # include <Evil.h>
28 #endif
29
30 #include "eina_config.h"
31 #include "eina_private.h"
32 #include "eina_error.h"
33 #include "eina_inlist.h"
34 #include "eina_log.h"
35 #include "eina_magic.h"
36
37 /*============================================================================*
38  *                                  Local                                     *
39  *============================================================================*/
40
41 /**
42  * @cond LOCAL
43  */
44
45 typedef struct _Eina_Magic_String Eina_Magic_String;
46 struct _Eina_Magic_String
47 {
48    EINA_INLIST;
49
50    char *string;
51    Eina_Magic magic;
52 };
53
54 static Eina_Inlist *strings = NULL;
55
56 /**
57  * @endcond
58  */
59
60 /*============================================================================*
61  *                                 Global                                     *
62  *============================================================================*/
63
64 /*============================================================================*
65  *                                   API                                      *
66  *============================================================================*/
67
68 /**
69  * @addtogroup Eina_Magic_Group Magic
70  *
71  * @brief These functions provide magic checks management for projects.
72  *
73  * @{
74  */
75
76 /**
77  * @internal
78  * @brief Initialize the magic string module.
79  *
80  * @return #EINA_TRUE on success, #EINA_FALSE on failure.
81  *
82  * This function sets up the magic string module of Eina. It is called by
83  * eina_init().
84  *
85  * @see eina_init()
86  */
87 Eina_Bool
88 eina_magic_string_init(void)
89 {
90    return EINA_TRUE;
91 }
92
93 /**
94  * @internal
95  * @brief Shut down the magic string module.
96  *
97  * @return #EINA_TRUE on success, #EINA_FALSE on failure.
98  *
99  * This function shuts down the magic string module set up by
100  * eina_magic string_init(). It is called by eina_shutdown().
101  *
102  * @see eina_shutdown()
103  */
104 Eina_Bool
105 eina_magic_string_shutdown(void)
106 {
107    /* Free all strings. */
108    while (strings)
109      {
110         Eina_Magic_String *tmp = (Eina_Magic_String*) strings;
111         strings = eina_inlist_remove(strings, strings);
112
113         free(tmp->string);
114         free(tmp);
115      }
116
117    return EINA_TRUE;
118 }
119
120 /**
121  * @brief Return the string associated to the given magic identifier.
122  *
123  * @param magic The magic identifier.
124  * @return The string associated to the identifier.
125  *
126  * This function returns the string associated to @p magic. If none
127  * are found, the this function returns @c NULL. The returned value
128  * must not be freed.
129  */
130 EAPI const char*
131 eina_magic_string_get(Eina_Magic magic)
132 {
133    Eina_Magic_String *ems;
134
135    EINA_INLIST_FOREACH(strings, ems)
136      if (ems->magic == magic)
137        return ems->string;
138
139    return NULL;
140 }
141
142 /**
143  * @brief Set the string associated to the given magic identifier.
144  *
145  * @param magic The magic identifier.
146  * @param The string associated to the identifier.
147  *
148  * This function sets the string @p magic_name to @p magic. If a
149  * string is already associated to @p magic, then it is freed and @p
150  * magic_name is duplicated. Otherwise, it is added to the list of
151  * magic strings.
152  */
153 EAPI void
154 eina_magic_string_set(Eina_Magic magic, const char *magic_name)
155 {
156    Eina_Magic_String *ems;
157
158    EINA_INLIST_FOREACH(strings, ems)
159      if (ems->magic == magic)
160        {
161           free(ems->string);
162           if (magic_name)
163             ems->string = strdup(magic_name);
164           else
165             ems->string = NULL;
166           return ;
167        }
168
169    ems = malloc(sizeof (Eina_Magic_String));
170    if (!ems)
171      return;
172    ems->magic = magic;
173    if (magic_name)
174      ems->string = strdup(magic_name);
175    else
176      ems->string = NULL;
177
178    strings = eina_inlist_prepend(strings, EINA_INLIST_GET(ems));
179 }
180
181 #ifdef eina_magic_fail
182 # undef eina_magic_fail
183 #endif
184
185 /**
186  * @brief Display a message or abort is a magic check failed.
187  *
188  * @param d The checked data pointer.
189  * @param m The magic identifer to check.
190  * @param req_m The requested magic identifier to check.
191  * @param file The file in which the magic check failed.
192  * @param fcn The function in which the magic check failed.
193  * @param line The line at which the magic check failed.
194  *
195  * This function displays an error message if a magic check has
196  * failed, using the following logic in the following order:
197  * @li If @p d is @c NULL, a message warns about a @c NULL pointer.
198  * @li Otherwise, if @p m is equal to #EINA_MAGIC_NONE, a message
199  * warns about a handle that was already freed.
200  * @li Otherwise, if @p m is equal to @p req_m, a message warns about
201  * a handle that is of wrong type.
202  * @li Otherwise, a message warns you about ab-using that function...
203  *
204  * If the environment variable EINA_ERROR_ABORT is set, abort() is
205  * called and the program stops. It is useful for debugging programs
206  * with gdb.
207  */
208 EAPI void
209 eina_magic_fail(void *d, Eina_Magic m, Eina_Magic req_m, const char *file, const char *fnc, int line)
210 {
211    if (!d)
212      eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
213                     file, fnc, line,
214                     "*** Eina Magic Check Failed !!!\n"
215                     "    Input handle pointer is NULL !\n"
216                     "*** NAUGHTY PROGRAMMER!!!\n"
217                     "*** SPANK SPANK SPANK!!!\n"
218                     "*** Now go fix your code. Tut tut tut!\n"
219                     "\n");
220    else
221      if (m == EINA_MAGIC_NONE)
222        eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
223                       file, fnc, line,
224                       "*** Eina Magic Check Failed !!!\n"
225                       "    Input handle has already been freed!\n"
226                       "*** NAUGHTY PROGRAMMER!!!\n"
227                       "*** SPANK SPANK SPANK!!!\n"
228                       "*** Now go fix your code. Tut tut tut!\n"
229                       "\n");
230      else
231        if (m != req_m)
232        eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
233                       file, fnc, line,
234                       "*** Eina Magic Check Failed !!!\n"
235                       "    Input handle is wrong type\n"
236                       "    Expected: %08x - %s\n"
237                       "    Supplied: %08x - %s\n"
238                       "*** NAUGHTY PROGRAMMER!!!\n"
239                       "*** SPANK SPANK SPANK!!!\n"
240                       "*** Now go fix your code. Tut tut tut!\n"
241                       "\n",
242                       req_m, eina_magic_string_get(req_m),
243                       m, eina_magic_string_get(m));
244        else
245        eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
246                       file, fnc, line,
247                       "*** Eina Magic Check Failed !!!\n"
248                       "    Why did you call me !\n"
249                       "*** NAUGHTY PROGRAMMER!!!\n"
250                       "*** SPANK SPANK SPANK!!!\n"
251                       "*** Now go fix your code. Tut tut tut!\n"
252                       "\n");
253 }
254
255 /**
256  * @}
257  */