2008-08-06 11:15:24 -07:00
|
|
|
/* EINA - EFL data type library
|
|
|
|
* Copyright (C) 2008 Cedric Bail
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library;
|
|
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2008-09-26 04:41:55 -07:00
|
|
|
#include <stdlib.h>
|
2008-08-28 00:46:42 -07:00
|
|
|
#include <string.h>
|
|
|
|
|
2008-10-16 14:31:51 -07:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
2008-09-26 04:41:55 -07:00
|
|
|
#include "eina_config.h"
|
2008-09-25 02:02:41 -07:00
|
|
|
#include "eina_private.h"
|
2008-09-25 07:46:48 -07:00
|
|
|
#include "eina_error.h"
|
2009-09-03 18:37:11 -07:00
|
|
|
#include "eina_log.h"
|
2009-09-06 19:33:54 -07:00
|
|
|
|
|
|
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
|
|
|
#include "eina_safety_checks.h"
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_magic.h"
|
2008-07-31 08:08:19 -07:00
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Local *
|
|
|
|
*============================================================================*/
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2009-06-22 13:03:58 -07:00
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
2008-07-31 08:08:19 -07:00
|
|
|
typedef struct _Eina_Magic_String Eina_Magic_String;
|
|
|
|
struct _Eina_Magic_String
|
|
|
|
{
|
|
|
|
Eina_Magic magic;
|
2009-09-06 20:32:22 -07:00
|
|
|
Eina_Bool string_allocated;
|
|
|
|
const char *string;
|
2008-07-31 08:08:19 -07:00
|
|
|
};
|
|
|
|
|
2009-09-06 19:33:54 -07:00
|
|
|
static int _eina_magic_string_log_dom = -1;
|
|
|
|
|
2009-09-06 21:23:05 -07:00
|
|
|
#ifdef ERR
|
|
|
|
#undef ERR
|
|
|
|
#endif
|
2009-09-06 19:33:54 -07:00
|
|
|
#define ERR(...) EINA_LOG_DOM_ERR(_eina_magic_string_log_dom, __VA_ARGS__)
|
2009-09-06 21:23:05 -07:00
|
|
|
|
|
|
|
#ifdef DBG
|
|
|
|
#undef DBG
|
|
|
|
#endif
|
2009-09-06 19:33:54 -07:00
|
|
|
#define DBG(...) EINA_LOG_DOM_DBG(_eina_magic_string_log_dom, __VA_ARGS__)
|
|
|
|
|
|
|
|
static Eina_Magic_String *_eina_magic_strings = NULL;
|
|
|
|
static size_t _eina_magic_strings_count = 0;
|
|
|
|
static size_t _eina_magic_strings_allocated = 0;
|
|
|
|
static Eina_Bool _eina_magic_strings_dirty = 0;
|
|
|
|
|
|
|
|
static int
|
|
|
|
_eina_magic_strings_sort_cmp(const void *p1, const void *p2)
|
|
|
|
{
|
|
|
|
const Eina_Magic_String *a = p1, *b = p2;
|
|
|
|
return a->magic - b->magic;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_eina_magic_strings_find_cmp(const void *p1, const void *p2)
|
|
|
|
{
|
2011-12-05 02:17:57 -08:00
|
|
|
Eina_Magic a = (Eina_Magic)(size_t)p1;
|
2009-09-06 19:33:54 -07:00
|
|
|
const Eina_Magic_String *b = p2;
|
|
|
|
return a - b->magic;
|
|
|
|
}
|
2008-07-31 08:08:19 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
static Eina_Magic_String *
|
|
|
|
_eina_magic_strings_alloc(void)
|
|
|
|
{
|
|
|
|
size_t idx;
|
|
|
|
|
|
|
|
if (_eina_magic_strings_count == _eina_magic_strings_allocated)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
void *tmp;
|
|
|
|
size_t size;
|
2009-09-06 20:32:22 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (EINA_UNLIKELY(_eina_magic_strings_allocated == 0))
|
|
|
|
size = 48;
|
|
|
|
else
|
|
|
|
size = _eina_magic_strings_allocated + 16;
|
2009-09-06 20:32:22 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
tmp = realloc(_eina_magic_strings, sizeof(Eina_Magic_String) * size);
|
|
|
|
if (!tmp)
|
|
|
|
{
|
|
|
|
ERR("could not realloc magic_strings from %zu to %zu buckets.",
|
|
|
|
_eina_magic_strings_allocated, size);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
_eina_magic_strings = tmp;
|
|
|
|
_eina_magic_strings_allocated = size;
|
2009-09-06 20:32:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
idx = _eina_magic_strings_count;
|
|
|
|
_eina_magic_strings_count++;
|
|
|
|
return _eina_magic_strings + idx;
|
|
|
|
}
|
|
|
|
|
2009-06-22 13:03:58 -07:00
|
|
|
/**
|
|
|
|
* @endcond
|
|
|
|
*/
|
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Global *
|
|
|
|
*============================================================================*/
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2012-01-09 15:14:04 -08:00
|
|
|
EAPI Eina_Error EINA_ERROR_MAGIC_FAILED = 0;
|
|
|
|
|
|
|
|
static const char EINA_ERROR_MAGIC_FAILED_STR[] = "Magic check failed.";
|
|
|
|
|
2009-06-22 13:03:58 -07:00
|
|
|
/**
|
2009-09-06 15:21:56 -07:00
|
|
|
* @internal
|
|
|
|
* @brief Initialize the magic string module.
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* This function sets up the magic string module of Eina. It is called by
|
|
|
|
* eina_init().
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
|
|
|
* @see eina_init()
|
|
|
|
*/
|
2009-09-06 15:21:56 -07:00
|
|
|
Eina_Bool
|
2008-10-10 02:33:40 -07:00
|
|
|
eina_magic_string_init(void)
|
2008-07-31 08:08:19 -07:00
|
|
|
{
|
2009-09-06 19:33:54 -07:00
|
|
|
_eina_magic_string_log_dom = eina_log_domain_register
|
2010-07-27 19:37:05 -07:00
|
|
|
("eina_magic_string", EINA_LOG_COLOR_DEFAULT);
|
2009-09-06 19:33:54 -07:00
|
|
|
if (_eina_magic_string_log_dom < 0)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_LOG_ERR("Could not register log domain: eina_magic_string");
|
|
|
|
return EINA_FALSE;
|
2009-09-06 19:33:54 -07:00
|
|
|
}
|
2012-01-09 15:14:04 -08:00
|
|
|
EINA_ERROR_MAGIC_FAILED = eina_error_msg_static_register(
|
|
|
|
EINA_ERROR_MAGIC_FAILED_STR);
|
2009-09-06 19:33:54 -07:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
return EINA_TRUE;
|
2008-07-31 08:08:19 -07:00
|
|
|
}
|
|
|
|
|
2009-06-22 13:03:58 -07:00
|
|
|
/**
|
2009-09-06 15:21:56 -07:00
|
|
|
* @internal
|
|
|
|
* @brief Shut down the magic string module.
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* This function shuts down the magic string module set up by
|
|
|
|
* eina_magic string_init(). It is called by eina_shutdown().
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
|
|
|
* @see eina_shutdown()
|
|
|
|
*/
|
2009-09-06 15:21:56 -07:00
|
|
|
Eina_Bool
|
2008-10-10 02:33:40 -07:00
|
|
|
eina_magic_string_shutdown(void)
|
2008-07-31 08:08:19 -07:00
|
|
|
{
|
2009-09-06 20:32:22 -07:00
|
|
|
Eina_Magic_String *ems, *ems_end;
|
2008-09-26 04:41:55 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
ems = _eina_magic_strings;
|
|
|
|
ems_end = ems + _eina_magic_strings_count;
|
|
|
|
|
|
|
|
for (; ems < ems_end; ems++)
|
2010-07-27 19:37:05 -07:00
|
|
|
if (ems->string_allocated)
|
|
|
|
free((char *)ems->string);
|
2009-09-06 19:33:54 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
free(_eina_magic_strings);
|
2009-09-06 19:33:54 -07:00
|
|
|
_eina_magic_strings = NULL;
|
|
|
|
_eina_magic_strings_count = 0;
|
|
|
|
_eina_magic_strings_allocated = 0;
|
|
|
|
|
|
|
|
eina_log_domain_unregister(_eina_magic_string_log_dom);
|
|
|
|
_eina_magic_string_log_dom = -1;
|
2008-07-31 08:08:19 -07:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
return EINA_TRUE;
|
2008-07-31 08:08:19 -07:00
|
|
|
}
|
|
|
|
|
2009-12-27 00:45:30 -08:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* API *
|
|
|
|
*============================================================================*/
|
|
|
|
EAPI const char *
|
2008-07-31 08:08:19 -07:00
|
|
|
eina_magic_string_get(Eina_Magic magic)
|
|
|
|
{
|
|
|
|
Eina_Magic_String *ems;
|
|
|
|
|
2009-09-06 19:33:54 -07:00
|
|
|
if (!_eina_magic_strings)
|
2010-07-27 19:37:05 -07:00
|
|
|
return "(none)";
|
2009-09-06 19:33:54 -07:00
|
|
|
|
|
|
|
if (_eina_magic_strings_dirty)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
qsort(_eina_magic_strings, _eina_magic_strings_count,
|
|
|
|
sizeof(Eina_Magic_String), _eina_magic_strings_sort_cmp);
|
|
|
|
_eina_magic_strings_dirty = 0;
|
2009-09-06 19:33:54 -07:00
|
|
|
}
|
2008-07-31 08:08:19 -07:00
|
|
|
|
2011-12-05 02:17:57 -08:00
|
|
|
ems = bsearch((void *)(size_t)magic, _eina_magic_strings,
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_magic_strings_count, sizeof(Eina_Magic_String),
|
|
|
|
_eina_magic_strings_find_cmp);
|
2009-09-06 19:33:54 -07:00
|
|
|
if (ems)
|
2010-07-27 19:37:05 -07:00
|
|
|
return ems->string ? ems->string : "(undefined)";
|
|
|
|
|
2010-02-11 10:54:04 -08:00
|
|
|
return "(unknown)";
|
2008-07-31 08:08:19 -07:00
|
|
|
}
|
|
|
|
|
2009-09-06 19:33:54 -07:00
|
|
|
EAPI Eina_Bool
|
2008-07-31 08:08:19 -07:00
|
|
|
eina_magic_string_set(Eina_Magic magic, const char *magic_name)
|
|
|
|
{
|
|
|
|
Eina_Magic_String *ems;
|
|
|
|
|
2009-09-06 19:33:54 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE);
|
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
ems = _eina_magic_strings_alloc();
|
|
|
|
if (!ems)
|
2010-07-27 19:37:05 -07:00
|
|
|
return EINA_FALSE;
|
2009-09-06 19:33:54 -07:00
|
|
|
|
2008-07-31 08:08:19 -07:00
|
|
|
ems->magic = magic;
|
2009-09-06 20:32:22 -07:00
|
|
|
ems->string_allocated = EINA_TRUE;
|
2009-09-06 19:33:54 -07:00
|
|
|
ems->string = strdup(magic_name);
|
|
|
|
if (!ems->string)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
ERR("could not allocate string '%s'", magic_name);
|
|
|
|
_eina_magic_strings_count--;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2008-07-31 08:08:19 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
_eina_magic_strings_dirty = 1;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
eina_magic_string_static_set(Eina_Magic magic, const char *magic_name)
|
|
|
|
{
|
|
|
|
Eina_Magic_String *ems;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE);
|
|
|
|
|
|
|
|
ems = _eina_magic_strings_alloc();
|
|
|
|
if (!ems)
|
2010-07-27 19:37:05 -07:00
|
|
|
return EINA_FALSE;
|
2009-09-06 20:32:22 -07:00
|
|
|
|
|
|
|
ems->magic = magic;
|
|
|
|
ems->string_allocated = EINA_FALSE;
|
|
|
|
ems->string = magic_name;
|
|
|
|
|
2009-09-06 19:33:54 -07:00
|
|
|
_eina_magic_strings_dirty = 1;
|
|
|
|
return EINA_TRUE;
|
2008-07-31 08:08:19 -07:00
|
|
|
}
|
|
|
|
|
2009-09-01 05:17:13 -07:00
|
|
|
#ifdef eina_magic_fail
|
|
|
|
# undef eina_magic_fail
|
|
|
|
#endif
|
|
|
|
|
2008-07-31 08:08:19 -07:00
|
|
|
EAPI void
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_magic_fail(void *d,
|
|
|
|
Eina_Magic m,
|
|
|
|
Eina_Magic req_m,
|
|
|
|
const char *file,
|
|
|
|
const char *fnc,
|
|
|
|
int line)
|
2008-07-31 08:08:19 -07:00
|
|
|
{
|
2012-01-09 15:14:04 -08:00
|
|
|
eina_error_set(EINA_ERROR_MAGIC_FAILED);
|
2008-07-31 08:08:19 -07:00
|
|
|
if (!d)
|
2012-12-24 01:16:56 -08:00
|
|
|
eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_ERR,
|
2010-07-27 19:37:05 -07:00
|
|
|
file, fnc, line,
|
|
|
|
"*** Eina Magic Check Failed !!!\n"
|
|
|
|
" Input handle pointer is NULL !\n"
|
|
|
|
"*** NAUGHTY PROGRAMMER!!!\n"
|
|
|
|
"*** SPANK SPANK SPANK!!!\n"
|
|
|
|
"*** Now go fix your code. Tut tut tut!\n"
|
|
|
|
"\n");
|
|
|
|
else
|
|
|
|
if (m == EINA_MAGIC_NONE)
|
|
|
|
eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
|
|
|
|
file, fnc, line,
|
2013-01-23 17:37:20 -08:00
|
|
|
"*** Eina Magic Check Failed at %d !!!\n"
|
2010-07-27 19:37:05 -07:00
|
|
|
" Input handle has already been freed!\n"
|
|
|
|
"*** NAUGHTY PROGRAMMER!!!\n"
|
|
|
|
"*** SPANK SPANK SPANK!!!\n"
|
|
|
|
"*** Now go fix your code. Tut tut tut!\n"
|
2013-01-23 17:37:20 -08:00
|
|
|
"\n", d);
|
2010-07-27 19:37:05 -07:00
|
|
|
else
|
|
|
|
if (m != req_m)
|
|
|
|
eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
|
|
|
|
file, fnc, line,
|
2013-01-23 17:37:20 -08:00
|
|
|
"*** Eina Magic Check Failed at %p !!!\n"
|
2010-07-27 19:37:05 -07:00
|
|
|
" Input handle is wrong type\n"
|
|
|
|
" Expected: %08x - %s\n"
|
|
|
|
" Supplied: %08x - %s\n"
|
|
|
|
"*** NAUGHTY PROGRAMMER!!!\n"
|
|
|
|
"*** SPANK SPANK SPANK!!!\n"
|
|
|
|
"*** Now go fix your code. Tut tut tut!\n"
|
|
|
|
"\n",
|
2013-01-23 17:37:20 -08:00
|
|
|
d, req_m, eina_magic_string_get(req_m),
|
2010-07-27 19:37:05 -07:00
|
|
|
m, eina_magic_string_get(m));
|
2009-09-03 18:37:11 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL,
|
|
|
|
file, fnc, line,
|
|
|
|
"*** Eina Magic Check Failed !!!\n"
|
|
|
|
" Why did you call me !\n"
|
|
|
|
"*** NAUGHTY PROGRAMMER!!!\n"
|
|
|
|
"*** SPANK SPANK SPANK!!!\n"
|
|
|
|
"*** Now go fix your code. Tut tut tut!\n"
|
|
|
|
"\n");
|
2008-07-31 08:08:19 -07:00
|
|
|
}
|
|
|
|
|
2009-06-22 13:03:58 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|