From 2ed64a7ae95fba30b7beb9b0310601f747ddb7a3 Mon Sep 17 00:00:00 2001 From: barbieri Date: Mon, 7 Sep 2009 02:33:54 +0000 Subject: [PATCH] API BREAK: eina_magic_string_set() does not change existing strings anymore. It's pointless to be able to change magic number string after it's created, so let's avoid walking the existing list and just remove places where strings were being duplicated (list/array both inited magic strings for accessor/iterators). Also an optimization, register using an array and sort it before searching. Sort will just happen when array was changed, and this is just done when eina_magic_string_get() is called. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@42310 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/include/eina_magic.h | 2 +- src/lib/eina_accessor.c | 34 ++++++++++++ src/lib/eina_array.c | 2 - src/lib/eina_iterator.c | 34 ++++++++++++ src/lib/eina_list.c | 2 - src/lib/eina_magic.c | 142 +++++++++++++++++++++++++++++++++-------------- src/lib/eina_main.c | 4 ++ 7 files changed, 174 insertions(+), 46 deletions(-) diff --git a/src/include/eina_magic.h b/src/include/eina_magic.h index 1a97947..796d357 100644 --- a/src/include/eina_magic.h +++ b/src/include/eina_magic.h @@ -42,7 +42,7 @@ typedef unsigned int Eina_Magic; * An abstract type for a magic number. */ EAPI const char* eina_magic_string_get(Eina_Magic magic) EINA_PURE EINA_WARN_UNUSED_RESULT; -EAPI void eina_magic_string_set(Eina_Magic magic, const char *magic_name) EINA_ARG_NONNULL(2); +EAPI Eina_Bool eina_magic_string_set(Eina_Magic magic, const char *magic_name) EINA_ARG_NONNULL(2); /** * @def EINA_MAGIC_NONE diff --git a/src/lib/eina_accessor.c b/src/lib/eina_accessor.c index 1708fc8..7130c2f 100644 --- a/src/lib/eina_accessor.c +++ b/src/lib/eina_accessor.c @@ -79,6 +79,40 @@ */ /** + * @internal + * @brief Initialize the accessor module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the accessor module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_accessor_init(void) +{ + return eina_magic_string_set(EINA_MAGIC_ACCESSOR, "Eina Accessor"); +} + +/** + * @internal + * @brief Shut down the accessor module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the accessor module set up by + * eina_accessor_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_accessor_shutdown(void) +{ + return EINA_TRUE; +} + +/** * @brief Free an accessor. * * @param accessor The accessor to free. diff --git a/src/lib/eina_array.c b/src/lib/eina_array.c index eb28d8c..9fa5edc 100644 --- a/src/lib/eina_array.c +++ b/src/lib/eina_array.c @@ -338,8 +338,6 @@ eina_array_init(void) return EINA_FALSE; } - eina_magic_string_set(EINA_MAGIC_ITERATOR, "Eina Iterator"); - eina_magic_string_set(EINA_MAGIC_ACCESSOR, "Eina Accessor"); eina_magic_string_set(EINA_MAGIC_ARRAY, "Eina Array"); eina_magic_string_set(EINA_MAGIC_ARRAY_ITERATOR, "Eina Array Iterator"); eina_magic_string_set(EINA_MAGIC_ARRAY_ACCESSOR, "Eina Array Accessor"); diff --git a/src/lib/eina_iterator.c b/src/lib/eina_iterator.c index e64f899..ff31902 100644 --- a/src/lib/eina_iterator.c +++ b/src/lib/eina_iterator.c @@ -80,6 +80,40 @@ */ /** + * @internal + * @brief Initialize the iterator module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the iterator module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_iterator_init(void) +{ + return eina_magic_string_set(EINA_MAGIC_ITERATOR, "Eina Iterator"); +} + +/** + * @internal + * @brief Shut down the iterator module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the iterator module set up by + * eina_iterator_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_iterator_shutdown(void) +{ + return EINA_TRUE; +} + +/** * @brief Free an iterator. * * @param iterator The iterator to free. diff --git a/src/lib/eina_list.c b/src/lib/eina_list.c index 1d68421..54b91b8 100644 --- a/src/lib/eina_list.c +++ b/src/lib/eina_list.c @@ -487,8 +487,6 @@ eina_list_init(void) goto on_init_fail; } - eina_magic_string_set(EINA_MAGIC_ITERATOR, "Eina Iterator"); - eina_magic_string_set(EINA_MAGIC_ACCESSOR, "Eina Accessor"); eina_magic_string_set(EINA_MAGIC_LIST, "Eina List"); eina_magic_string_set(EINA_MAGIC_LIST_ITERATOR, "Eina List Iterator"); eina_magic_string_set(EINA_MAGIC_LIST_ACCESSOR, "Eina List Accessor"); diff --git a/src/lib/eina_magic.c b/src/lib/eina_magic.c index bd7f583..8dd3b86 100644 --- a/src/lib/eina_magic.c +++ b/src/lib/eina_magic.c @@ -30,8 +30,10 @@ #include "eina_config.h" #include "eina_private.h" #include "eina_error.h" -#include "eina_inlist.h" #include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" #include "eina_magic.h" /*============================================================================* @@ -45,13 +47,34 @@ typedef struct _Eina_Magic_String Eina_Magic_String; struct _Eina_Magic_String { - EINA_INLIST; - - char *string; Eina_Magic magic; + char *string; }; -static Eina_Inlist *strings = NULL; +static int _eina_magic_string_log_dom = -1; + +#define ERR(...) EINA_LOG_DOM_ERR(_eina_magic_string_log_dom, __VA_ARGS__) +#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) +{ + Eina_Magic a = (long)p1; + const Eina_Magic_String *b = p2; + return a - b->magic; +} /** * @endcond @@ -87,6 +110,14 @@ static Eina_Inlist *strings = NULL; Eina_Bool eina_magic_string_init(void) { + _eina_magic_string_log_dom = eina_log_domain_register + ("eina_magic_string", EINA_LOG_COLOR_DEFAULT); + if (_eina_magic_string_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_magic_string"); + return EINA_FALSE; + } + return EINA_TRUE; } @@ -104,15 +135,18 @@ eina_magic_string_init(void) Eina_Bool eina_magic_string_shutdown(void) { - /* Free all strings. */ - while (strings) - { - Eina_Magic_String *tmp = (Eina_Magic_String*) strings; - strings = eina_inlist_remove(strings, strings); + size_t i; - free(tmp->string); - free(tmp); - } + for (i = 0; i < _eina_magic_strings_count; i++) + free(_eina_magic_strings[i].string); + + free(_eina_magic_strings); + _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; return EINA_TRUE; } @@ -132,10 +166,21 @@ eina_magic_string_get(Eina_Magic magic) { Eina_Magic_String *ems; - EINA_INLIST_FOREACH(strings, ems) - if (ems->magic == magic) - return ems->string; + if (!_eina_magic_strings) + return NULL; + if (_eina_magic_strings_dirty) + { + qsort(_eina_magic_strings, _eina_magic_strings_count, + sizeof(Eina_Magic_String), _eina_magic_strings_sort_cmp); + _eina_magic_strings_dirty = 0; + } + + ems = bsearch((void *)(long)magic, _eina_magic_strings, + _eina_magic_strings_count, sizeof(Eina_Magic_String), + _eina_magic_strings_find_cmp); + if (ems) + return ems->string; return NULL; } @@ -143,39 +188,54 @@ eina_magic_string_get(Eina_Magic magic) * @brief Set the string associated to the given magic identifier. * * @param magic The magic identifier. - * @param The string associated to the identifier. + * @param The string associated to the identifier, must not be @c NULL. * - * This function sets the string @p magic_name to @p magic. If a - * string is already associated to @p magic, then it is freed and @p - * magic_name is duplicated. Otherwise, it is added to the list of - * magic strings. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets the string @p magic_name to @p magic. It is not + * checked if number or string are already set, then you might end + * with duplicates in that case. */ -EAPI void +EAPI Eina_Bool eina_magic_string_set(Eina_Magic magic, const char *magic_name) { Eina_Magic_String *ems; - EINA_INLIST_FOREACH(strings, ems) - if (ems->magic == magic) - { - free(ems->string); - if (magic_name) - ems->string = strdup(magic_name); - else - ems->string = NULL; - return ; - } - - ems = malloc(sizeof (Eina_Magic_String)); - if (!ems) - return; + EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE); + + if (_eina_magic_strings_count == _eina_magic_strings_allocated) + { + void *tmp; + size_t size; + + if (EINA_UNLIKELY(_eina_magic_strings_allocated == 0)) + size = 48; + else + size = _eina_magic_strings_allocated + 16; + + 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 EINA_FALSE; + } + _eina_magic_strings = tmp; + _eina_magic_strings_allocated = size; + } + + ems = _eina_magic_strings + _eina_magic_strings_count; ems->magic = magic; - if (magic_name) - ems->string = strdup(magic_name); - else - ems->string = NULL; + ems->string = strdup(magic_name); + if (!ems->string) + { + ERR("could not allocate string '%s'", magic_name); + return EINA_FALSE; + } - strings = eina_inlist_prepend(strings, EINA_INLIST_GET(ems)); + _eina_magic_strings_count++; + _eina_magic_strings_dirty = 1; + return EINA_TRUE; } #ifdef eina_magic_fail diff --git a/src/lib/eina_main.c b/src/lib/eina_main.c index 0125a9e..d39da42 100644 --- a/src/lib/eina_main.c +++ b/src/lib/eina_main.c @@ -61,6 +61,8 @@ S(log); S(error); S(safety_checks); S(magic_string); +S(iterator); +S(accessor); S(array); S(module); S(mempool); @@ -86,6 +88,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = { S(error), S(safety_checks), S(magic_string), + S(iterator), + S(accessor), S(array), S(module), S(mempool), -- 2.7.4