API BREAK: eina_magic_string_set() does not change existing strings anymore.
authorbarbieri <barbieri>
Mon, 7 Sep 2009 02:33:54 +0000 (02:33 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 7 Sep 2009 02:33:54 +0000 (02:33 +0000)
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
src/lib/eina_accessor.c
src/lib/eina_array.c
src/lib/eina_iterator.c
src/lib/eina_list.c
src/lib/eina_magic.c
src/lib/eina_main.c

index 1a97947..796d357 100644 (file)
@@ -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
index 1708fc8..7130c2f 100644 (file)
  */
 
 /**
+ * @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.
index eb28d8c..9fa5edc 100644 (file)
@@ -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");
index e64f899..ff31902 100644 (file)
  */
 
 /**
+ * @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.
index 1d68421..54b91b8 100644 (file)
@@ -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");
index bd7f583..8dd3b86 100644 (file)
 #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"
 
 /*============================================================================*
 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
index 0125a9e..d39da42 100644 (file)
@@ -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),