From: Enlightenment S. <no-...@en...> - 2008-10-28 00:31:13
|
Log: Cheap way to get strlen of a shared string. it's not safe, but it's faster and can help for large strings, maximum cost is 4 comparisons plus one pointer access. Author: barbieri Date: 2008-10-27 17:31:09 -0700 (Mon, 27 Oct 2008) New Revision: 37257 Modified: trunk/eina/src/include/eina_stringshare.h trunk/eina/src/lib/eina_stringshare.c Modified: trunk/eina/src/include/eina_stringshare.h =================================================================== --- trunk/eina/src/include/eina_stringshare.h 2008-10-28 00:18:31 UTC (rev 37256) +++ trunk/eina/src/include/eina_stringshare.h 2008-10-28 00:31:09 UTC (rev 37257) @@ -69,6 +69,7 @@ EAPI int eina_stringshare_shutdown(void); EAPI const char *eina_stringshare_add(const char *str); EAPI void eina_stringshare_del(const char *str); +EAPI int eina_stringshare_strlen(const char *str); EAPI void eina_stringshare_dump(void); /** Modified: trunk/eina/src/lib/eina_stringshare.c =================================================================== --- trunk/eina/src/lib/eina_stringshare.c 2008-10-28 00:18:31 UTC (rev 37256) +++ trunk/eina/src/lib/eina_stringshare.c 2008-10-28 00:31:09 UTC (rev 37257) @@ -891,6 +891,36 @@ if (getenv("EINA_ERROR_ABORT")) abort(); } +/** + * @brief Note that the given string @b must be shared. + * + * @param str the shared string to know the length. It is safe to + * give NULL, in that case -1 is returned. + * + * This function is a cheap way to known the length of a shared + * string. Note that if the given pointer is not shared or NULL, bad + * things will happen, likely a segmentation fault. If in doubt, try + * strlen(). + */ +EAPI int +eina_stringshare_strlen(const char *str) +{ + const Eina_Stringshare_Node *node; + + if (!str) + return -1; + + /* special cases */ + if (str[0] == '\0') return 0; + if (str[1] == '\0') return 1; + if (str[2] == '\0') return 2; + if (str[3] == '\0') return 3; + + node = (void *)(str - sizeof(Eina_Stringshare_Node)); + EINA_MAGIC_CHECK_STRINGSHARE_NODE(node); + return node->length; +} + struct dumpinfo { int used, saved, dups, unique; |
From: Enlightenment S. <no-...@en...> - 2008-12-06 02:21:22
|
Log: Fix namespace: Eina_Foreach -> Eina_Hash_Foreach. Author: barbieri Date: 2008-12-05 18:21:17 -0800 (Fri, 05 Dec 2008) New Revision: 37950 Modified: trunk/eina/src/include/eina_hash.h trunk/eina/src/lib/eina_hash.c Modified: trunk/eina/src/include/eina_hash.h =================================================================== --- trunk/eina/src/include/eina_hash.h 2008-12-06 02:13:01 UTC (rev 37949) +++ trunk/eina/src/include/eina_hash.h 2008-12-06 02:21:17 UTC (rev 37950) @@ -96,9 +96,9 @@ EAPI Eina_Iterator * eina_hash_iterator_data_new(const Eina_Hash *hash); EAPI Eina_Iterator * eina_hash_iterator_tuple_new(const Eina_Hash *hash); -typedef Eina_Bool (*Eina_Foreach)(const Eina_Hash *hash, const void *key, void *data, void *fdata); +typedef Eina_Bool (*Eina_Hash_Foreach)(const Eina_Hash *hash, const void *key, void *data, void *fdata); EAPI void eina_hash_foreach(const Eina_Hash *hash, - Eina_Foreach cb, + Eina_Hash_Foreach cb, const void *fdata); /* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html) hash function Modified: trunk/eina/src/lib/eina_hash.c =================================================================== --- trunk/eina/src/lib/eina_hash.c 2008-12-06 02:13:01 UTC (rev 37949) +++ trunk/eina/src/lib/eina_hash.c 2008-12-06 02:21:17 UTC (rev 37950) @@ -44,7 +44,7 @@ typedef struct _Eina_Hash_Head Eina_Hash_Head; typedef struct _Eina_Hash_El Eina_Hash_El; -typedef struct _Eina_Hash_Foreach Eina_Hash_Foreach; +typedef struct _Eina_Hash_Foreach_Data Eina_Hash_Foreach_Data; typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash; typedef struct _Eina_Hash_Each Eina_Hash_Each; @@ -74,9 +74,9 @@ Eina_Bool begin : 1; }; -struct _Eina_Hash_Foreach +struct _Eina_Hash_Foreach_Data { - Eina_Foreach cb; + Eina_Hash_Foreach cb; const void *fdata; }; @@ -331,7 +331,7 @@ } static Eina_Bool -_eina_foreach_cb(const Eina_Hash *hash, Eina_Hash_Tuple *data, Eina_Hash_Foreach *fdata) +_eina_foreach_cb(const Eina_Hash *hash, Eina_Hash_Tuple *data, Eina_Hash_Foreach_Data *fdata) { return fdata->cb((Eina_Hash *) hash, data->key, data->data, (void*) fdata->fdata); } @@ -977,11 +977,11 @@ */ EAPI void eina_hash_foreach(const Eina_Hash *hash, - Eina_Foreach func, + Eina_Hash_Foreach func, const void *fdata) { Eina_Iterator *it; - Eina_Hash_Foreach foreach; + Eina_Hash_Foreach_Data foreach; foreach.cb = func; foreach.fdata = fdata; |
From: Enlightenment S. <no-...@en...> - 2008-12-06 03:41:07
|
Log: Make it possible to create iterators outside Eina. Many places in EFL we just create walk something, create a list with walked data, return, then the user walks it again and then deletes (which will walk again). For such cases it's way better to define iterators or accessors. I'm not moving any EFL code to it now, but if people are interested, things like evas_render_method_list(), evas_font_available_list(), evas_objects_at_xy_get(), evas_objects_in_rectangle_get(), evas_object_smart_members_get() are good candidates. If the subject is already using Eina list, then you can just use eina_list_iterator_new() and return it, otherwise you can define your own iterator, which is very easy. Author: barbieri Date: 2008-12-05 19:41:03 -0800 (Fri, 05 Dec 2008) New Revision: 37956 Modified: trunk/eina/src/include/eina_accessor.h trunk/eina/src/include/eina_iterator.h trunk/eina/src/include/eina_magic.h trunk/eina/src/include/eina_private.h trunk/eina/src/lib/eina_accessor.c trunk/eina/src/lib/eina_iterator.c Modified: trunk/eina/src/include/eina_accessor.h =================================================================== --- trunk/eina/src/include/eina_accessor.h 2008-12-06 03:18:12 UTC (rev 37955) +++ trunk/eina/src/include/eina_accessor.h 2008-12-06 03:41:03 UTC (rev 37956) @@ -20,6 +20,7 @@ #define EINA_ACCESSOR_H__ #include "eina_types.h" +#include "eina_magic.h" /** * @defgroup Eina_Accessor_Group Accessor Functions @@ -33,6 +34,25 @@ */ typedef struct _Eina_Accessor Eina_Accessor; +typedef Eina_Bool (*Eina_Accessor_Get_At_Callback)(Eina_Accessor *it, unsigned int index, void **data); +typedef void *(*Eina_Accessor_Get_Container_Callback)(Eina_Accessor *it); +typedef void (*Eina_Accessor_Free_Callback)(Eina_Accessor *it); + +struct _Eina_Accessor +{ +#define EINA_MAGIC_ACCESSOR 0x98761232 + EINA_MAGIC; + + Eina_Accessor_Get_At_Callback get_at; + Eina_Accessor_Get_Container_Callback get_container; + Eina_Accessor_Free_Callback free; +}; + +#define FUNC_ACCESSOR_GET_AT(Function) ((Eina_Accessor_Get_At_Callback)Function) +#define FUNC_ACCESSOR_GET_CONTAINER(Function) ((Eina_Accessor_Get_Container_Callback)Function) +#define FUNC_ACCESSOR_FREE(Function) ((Eina_Accessor_Free_Callback)Function) + + EAPI void eina_accessor_free (Eina_Accessor *accessor); EAPI Eina_Bool eina_accessor_data_get (Eina_Accessor *accessor, unsigned int position, void **data); Modified: trunk/eina/src/include/eina_iterator.h =================================================================== --- trunk/eina/src/include/eina_iterator.h 2008-12-06 03:18:12 UTC (rev 37955) +++ trunk/eina/src/include/eina_iterator.h 2008-12-06 03:41:03 UTC (rev 37956) @@ -20,6 +20,7 @@ #define EINA_ITERATOR_H__ #include "eina_types.h" +#include "eina_magic.h" /** * @defgroup Eina_Iterator_Group Iterator Functions @@ -33,6 +34,25 @@ */ typedef struct _Eina_Iterator Eina_Iterator; +typedef Eina_Bool (*Eina_Iterator_Next_Callback)(Eina_Iterator *it, void **data); +typedef void *(*Eina_Iterator_Get_Container_Callback)(Eina_Iterator *it); +typedef void (*Eina_Iterator_Free_Callback)(Eina_Iterator *it); + +struct _Eina_Iterator +{ +#define EINA_MAGIC_ITERATOR 0x98761233 + EINA_MAGIC; + + Eina_Iterator_Next_Callback next; + Eina_Iterator_Get_Container_Callback get_container; + Eina_Iterator_Free_Callback free; +}; + + +#define FUNC_ITERATOR_NEXT(Function) ((Eina_Iterator_Next_Callback)Function) +#define FUNC_ITERATOR_GET_CONTAINER(Function) ((Eina_Iterator_Get_Container_Callback)Function) +#define FUNC_ITERATOR_FREE(Function) ((Eina_Iterator_Free_Callback)Function) + EAPI void eina_iterator_free (Eina_Iterator *iterator); EAPI void *eina_iterator_container_get (Eina_Iterator *iterator); Modified: trunk/eina/src/include/eina_magic.h =================================================================== --- trunk/eina/src/include/eina_magic.h 2008-12-06 03:18:12 UTC (rev 37955) +++ trunk/eina/src/include/eina_magic.h 2008-12-06 03:41:03 UTC (rev 37956) @@ -52,8 +52,8 @@ #define eina_magic_string_get(Magic) (NULL) #define eina_magic_string_set(Magic, Magic_Name) ((void) 0) #define eina_magic_fail(d, m, req_m, file, fnx, line) ((void) 0) -#define eina_magic_string_init() (1) -#define eina_magic_string_shutdown() (0) +#define eina_magic_string_init() do {} while(0) +#define eina_magic_string_shutdown() do {} while(0) #endif Modified: trunk/eina/src/include/eina_private.h =================================================================== --- trunk/eina/src/include/eina_private.h 2008-12-06 03:18:12 UTC (rev 37955) +++ trunk/eina/src/include/eina_private.h 2008-12-06 03:41:03 UTC (rev 37956) @@ -50,9 +50,6 @@ #define READBUFSIZ 65536 /* eina magic types */ -#define EINA_MAGIC_ITERATOR 0x98761233 -#define EINA_MAGIC_ACCESSOR 0x98761232 - #define EINA_MAGIC_STRINGSHARE 0x98761234 #define EINA_MAGIC_STRINGSHARE_NODE 0x98761235 #define EINA_MAGIC_STRINGSHARE_HEAD 0x98761236 @@ -98,40 +95,6 @@ FREE(ptr); \ } while(0); -/* Iterator/accessor private type */ -typedef Eina_Bool (*Eina_Iterator_Next_Callback)(Eina_Iterator *it, void **data); -typedef void *(*Eina_Iterator_Get_Container_Callback)(Eina_Iterator *it); -typedef void (*Eina_Iterator_Free_Callback)(Eina_Iterator *it); -#define FUNC_ITERATOR_NEXT(Function) ((Eina_Iterator_Next_Callback)Function) -#define FUNC_ITERATOR_GET_CONTAINER(Function) ((Eina_Iterator_Get_Container_Callback)Function) -#define FUNC_ITERATOR_FREE(Function) ((Eina_Iterator_Free_Callback)Function) - -typedef Eina_Bool (*Eina_Accessor_Get_At_Callback)(Eina_Accessor *it, unsigned int index, void **data); -typedef void *(*Eina_Accessor_Get_Container_Callback)(Eina_Accessor *it); -typedef void (*Eina_Accessor_Free_Callback)(Eina_Accessor *it); - -#define FUNC_ACCESSOR_GET_AT(Function) ((Eina_Accessor_Get_At_Callback)Function) -#define FUNC_ACCESSOR_GET_CONTAINER(Function) ((Eina_Accessor_Get_Container_Callback)Function) -#define FUNC_ACCESSOR_FREE(Function) ((Eina_Accessor_Free_Callback)Function) - -struct _Eina_Iterator -{ - EINA_MAGIC; - - Eina_Iterator_Next_Callback next; - Eina_Iterator_Get_Container_Callback get_container; - Eina_Iterator_Free_Callback free; -}; - -struct _Eina_Accessor -{ - EINA_MAGIC; - - Eina_Accessor_Get_At_Callback get_at; - Eina_Accessor_Get_Container_Callback get_container; - Eina_Accessor_Free_Callback free; -}; - #endif /* EINA_PRIVATE_H_ */ Modified: trunk/eina/src/lib/eina_accessor.c =================================================================== --- trunk/eina/src/lib/eina_accessor.c 2008-12-06 03:18:12 UTC (rev 37955) +++ trunk/eina/src/lib/eina_accessor.c 2008-12-06 03:41:03 UTC (rev 37956) @@ -28,7 +28,26 @@ #include "eina_accessor.h" #include "eina_private.h" + /*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_MAGIC_CHECK_ACCESSOR(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ACCESSOR)) \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ACCESSOR); \ + } while(0); + +/** + * @endcond + */ + +/*============================================================================* * Global * *============================================================================*/ @@ -72,6 +91,7 @@ EAPI void eina_accessor_free(Eina_Accessor *accessor) { + EINA_MAGIC_CHECK_ACCESSOR(accessor); if (accessor) accessor->free(accessor); } @@ -87,6 +107,7 @@ EAPI void * eina_accessor_container_get(Eina_Accessor *accessor) { + EINA_MAGIC_CHECK_ACCESSOR(accessor); if (!accessor) return NULL; return accessor->get_container(accessor); } @@ -107,6 +128,7 @@ EAPI Eina_Bool eina_accessor_data_get(Eina_Accessor *accessor, unsigned int position, void **data) { + EINA_MAGIC_CHECK_ACCESSOR(accessor); if (!accessor) return EINA_FALSE; return accessor->get_at(accessor, position, data); } @@ -138,6 +160,8 @@ void *data; unsigned int i = start; + EINA_MAGIC_CHECK_ACCESSOR(accessor); + if (!accessor) return ; if (!(start < end)) return ; Modified: trunk/eina/src/lib/eina_iterator.c =================================================================== --- trunk/eina/src/lib/eina_iterator.c 2008-12-06 03:18:12 UTC (rev 37955) +++ trunk/eina/src/lib/eina_iterator.c 2008-12-06 03:41:03 UTC (rev 37956) @@ -29,6 +29,25 @@ #include "eina_private.h" /*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_MAGIC_CHECK_ITERATOR(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ITERATOR)) \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ITERATOR); \ + } while(0); + +/** + * @endcond + */ + + +/*============================================================================* * Global * *============================================================================*/ @@ -72,6 +91,7 @@ EAPI void eina_iterator_free(Eina_Iterator *iterator) { + EINA_MAGIC_CHECK_ITERATOR(iterator); if (iterator) iterator->free(iterator); } @@ -87,6 +107,7 @@ EAPI void * eina_iterator_container_get(Eina_Iterator *iterator) { + EINA_MAGIC_CHECK_ITERATOR(iterator); if (!iterator) return NULL; return iterator->get_container(iterator); } @@ -106,6 +127,7 @@ EAPI Eina_Bool eina_iterator_next(Eina_Iterator *iterator, void **data) { + EINA_MAGIC_CHECK_ITERATOR(iterator); if (!iterator) return EINA_FALSE; return iterator->next(iterator, data); } @@ -130,6 +152,8 @@ void *container; void *data; + EINA_MAGIC_CHECK_ITERATOR(iterator); + if (!iterator) return ; container = iterator->get_container(iterator); |
From: Enlightenment S. <no-...@en...> - 2008-12-06 06:17:20
|
Log: Fix couple of issues with MAGIC handling. eina_magic.h MUST include eina_config.h, otherwise it will not consider EINA_MAGIC stuff. Worse than that, some files were including that directly and were considering EINA_MAGIC attribute even if the file that alloc'ed the memory were not! Also add missing EINA_MAGIC_SET() to iterators and accessors. Author: barbieri Date: 2008-12-05 22:17:11 -0800 (Fri, 05 Dec 2008) New Revision: 37960 Modified: trunk/eina/src/include/eina_magic.h trunk/eina/src/lib/eina_hash.c trunk/eina/src/lib/eina_inlist.c trunk/eina/src/lib/eina_rbtree.c Modified: trunk/eina/src/include/eina_magic.h =================================================================== --- trunk/eina/src/include/eina_magic.h 2008-12-06 06:13:55 UTC (rev 37959) +++ trunk/eina/src/include/eina_magic.h 2008-12-06 06:17:11 UTC (rev 37960) @@ -19,6 +19,8 @@ #ifndef EINA_MAGIC_H_ #define EINA_MAGIC_H_ +#include "eina_config.h" + #ifdef EINA_MAGIC_DEBUG #include "eina_types.h" Modified: trunk/eina/src/lib/eina_hash.c =================================================================== --- trunk/eina/src/lib/eina_hash.c 2008-12-06 06:13:55 UTC (rev 37959) +++ trunk/eina/src/lib/eina_hash.c 2008-12-06 06:17:11 UTC (rev 37960) @@ -286,6 +286,8 @@ for (hash_num = 0; hash_num < EINA_HASH_BUCKET_SIZE; hash_num++) { + if (!hash->buckets[hash_num]) + continue; it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]); eina_iterator_foreach(it, EINA_EACH(_eina_hash_rbtree_each), &each); eina_iterator_free(it); @@ -1009,6 +1011,8 @@ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_hash_iterator_get_container); it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + return &it->iterator; } @@ -1030,6 +1034,8 @@ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_hash_iterator_get_container); it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + return &it->iterator; } @@ -1051,6 +1057,8 @@ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_hash_iterator_get_container); it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + return &it->iterator; } Modified: trunk/eina/src/lib/eina_inlist.c =================================================================== --- trunk/eina/src/lib/eina_inlist.c 2008-12-06 06:13:55 UTC (rev 37959) +++ trunk/eina/src/lib/eina_inlist.c 2008-12-06 06:17:11 UTC (rev 37960) @@ -355,6 +355,8 @@ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(eina_inlist_iterator_get_container); it->iterator.free = FUNC_ITERATOR_FREE(eina_inlist_iterator_free); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + return &it->iterator; } @@ -380,5 +382,7 @@ it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(eina_inlist_accessor_get_container); it->accessor.free = FUNC_ACCESSOR_FREE(eina_inlist_accessor_free); + EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR); + return &it->accessor; } Modified: trunk/eina/src/lib/eina_rbtree.c =================================================================== --- trunk/eina/src/lib/eina_rbtree.c 2008-12-06 06:13:55 UTC (rev 37959) +++ trunk/eina/src/lib/eina_rbtree.c 2008-12-06 06:17:11 UTC (rev 37960) @@ -179,6 +179,8 @@ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_rbtree_iterator_get_content); it->iterator.free = FUNC_ITERATOR_FREE(_eina_rbtree_iterator_free); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + return &it->iterator; on_error: |
From: Enlightenment S. <no-...@en...> - 2008-12-06 06:53:17
|
Log: Let valgrind help with EINA_MAGIC. Keep EINA_MAGIC at the end of the structure (WHEN POSSIBLE! Watch out flexible arrays like char str[] at the end!) this way if parts use EINA_MAGIC and others do not, it will possible overflow and valgrind can help us. WARNING: make uninstall before update! Then make clean and make install, check if everything is working with "make check". Author: barbieri Date: 2008-12-05 22:53:14 -0800 (Fri, 05 Dec 2008) New Revision: 37961 Modified: trunk/eina/src/include/eina_accessor.h trunk/eina/src/include/eina_array.h trunk/eina/src/include/eina_iterator.h trunk/eina/src/include/eina_list.h trunk/eina/src/lib/eina_array.c trunk/eina/src/lib/eina_list.c trunk/eina/src/lib/eina_rectangle.c Modified: trunk/eina/src/include/eina_accessor.h =================================================================== --- trunk/eina/src/include/eina_accessor.h 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/include/eina_accessor.h 2008-12-06 06:53:14 UTC (rev 37961) @@ -40,12 +40,12 @@ struct _Eina_Accessor { -#define EINA_MAGIC_ACCESSOR 0x98761232 - EINA_MAGIC; - Eina_Accessor_Get_At_Callback get_at; Eina_Accessor_Get_Container_Callback get_container; Eina_Accessor_Free_Callback free; + +#define EINA_MAGIC_ACCESSOR 0x98761232 + EINA_MAGIC; }; #define FUNC_ACCESSOR_GET_AT(Function) ((Eina_Accessor_Get_At_Callback)Function) Modified: trunk/eina/src/include/eina_array.h =================================================================== --- trunk/eina/src/include/eina_array.h 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/include/eina_array.h 2008-12-06 06:53:14 UTC (rev 37961) @@ -65,12 +65,12 @@ */ struct _Eina_Array { - EINA_MAGIC; - void **data; /**< Pointer to a vector of pointer to payload */ unsigned int total; /**< Total number of slot in the vector */ unsigned int count; /**< Number of activ slot in the vector */ unsigned int step; /**< How much must we grow the vector when it is full */ + + EINA_MAGIC; }; EAPI int eina_array_init (void); Modified: trunk/eina/src/include/eina_iterator.h =================================================================== --- trunk/eina/src/include/eina_iterator.h 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/include/eina_iterator.h 2008-12-06 06:53:14 UTC (rev 37961) @@ -40,12 +40,12 @@ struct _Eina_Iterator { -#define EINA_MAGIC_ITERATOR 0x98761233 - EINA_MAGIC; - Eina_Iterator_Next_Callback next; Eina_Iterator_Get_Container_Callback get_container; Eina_Iterator_Free_Callback free; + +#define EINA_MAGIC_ITERATOR 0x98761233 + EINA_MAGIC; }; Modified: trunk/eina/src/include/eina_list.h =================================================================== --- trunk/eina/src/include/eina_list.h 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/include/eina_list.h 2008-12-06 06:53:14 UTC (rev 37961) @@ -60,20 +60,19 @@ */ struct _Eina_List /** A linked list node */ { - EINA_MAGIC; - void *data; /**< Pointer to list element payload */ Eina_List *next; /**< Next member in the list */ Eina_List *prev; /**< Previous member in the list */ struct _Eina_List_Accounting *accounting; /**< Private list accounting info - don't touch */ + + EINA_MAGIC; }; struct _Eina_List_Accounting { - EINA_MAGIC; - Eina_List *last; unsigned int count; + EINA_MAGIC; }; Modified: trunk/eina/src/lib/eina_array.c =================================================================== --- trunk/eina/src/lib/eina_array.c 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/lib/eina_array.c 2008-12-06 06:53:14 UTC (rev 37961) @@ -72,20 +72,18 @@ { Eina_Iterator iterator; - EINA_MAGIC; - const Eina_Array *array; unsigned int index; + + EINA_MAGIC; }; typedef struct _Eina_Accessor_Array Eina_Accessor_Array; struct _Eina_Accessor_Array { Eina_Accessor accessor; - - EINA_MAGIC; - const Eina_Array *array; + EINA_MAGIC; }; static int _eina_array_init_count = 0; Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/lib/eina_list.c 2008-12-06 06:53:14 UTC (rev 37961) @@ -118,22 +118,22 @@ { Eina_Iterator iterator; - EINA_MAGIC; - const Eina_List *head; const Eina_List *current; + + EINA_MAGIC; }; struct _Eina_Accessor_List { Eina_Accessor accessor; - EINA_MAGIC; - const Eina_List *head; const Eina_List *current; unsigned int index; + + EINA_MAGIC; }; static int _eina_list_init_count = 0; Modified: trunk/eina/src/lib/eina_rectangle.c =================================================================== --- trunk/eina/src/lib/eina_rectangle.c 2008-12-06 06:17:11 UTC (rev 37960) +++ trunk/eina/src/lib/eina_rectangle.c 2008-12-06 06:53:14 UTC (rev 37961) @@ -42,22 +42,20 @@ struct _Eina_Rectangle_Pool { - EINA_MAGIC; - Eina_Inlist *head; void *data; unsigned int references; int w; int h; + EINA_MAGIC; }; struct _Eina_Rectangle_Alloc { EINA_INLIST; - EINA_MAGIC; - Eina_Rectangle_Pool *pool; + EINA_MAGIC; }; #define EINA_MAGIC_CHECK_RECTANGLE_POOL(d) \ |
From: Enlightenment S. <no-...@en...> - 2008-12-06 06:59:01
|
Log: refactor eina_hash_del*, expose simpler functions and avoid GCC hack. By using simpler functions for hash element deletion we can avoid the hack to shut up GCC warking about hash_num not being used. As these simple functions are more often needed than the catch-all, expose them as well. Author: barbieri Date: 2008-12-05 22:58:56 -0800 (Fri, 05 Dec 2008) New Revision: 37962 Modified: trunk/eina/src/include/eina_hash.h trunk/eina/src/lib/eina_hash.c Modified: trunk/eina/src/include/eina_hash.h =================================================================== --- trunk/eina/src/include/eina_hash.h 2008-12-06 06:53:14 UTC (rev 37961) +++ trunk/eina/src/include/eina_hash.h 2008-12-06 06:58:56 UTC (rev 37962) @@ -83,6 +83,12 @@ EAPI Eina_Bool eina_hash_direct_add_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash, const void *data); + +EAPI Eina_Bool eina_hash_del_by_key_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash); + +EAPI Eina_Bool eina_hash_del_by_key(Eina_Hash *hash, const void *key); +EAPI Eina_Bool eina_hash_del_by_data(Eina_Hash *hash, const void *data); + EAPI Eina_Bool eina_hash_del_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash, const void *data); Modified: trunk/eina/src/lib/eina_hash.c =================================================================== --- trunk/eina/src/lib/eina_hash.c 2008-12-06 06:53:14 UTC (rev 37961) +++ trunk/eina/src/lib/eina_hash.c 2008-12-06 06:58:56 UTC (rev 37962) @@ -755,57 +755,141 @@ return eina_hash_direct_add_by_hash(hash, key, key_length, key_hash, data); } +static Eina_Bool +_eina_hash_del_by_hash_el(Eina_Hash *hash, Eina_Hash_El *el, Eina_Hash_Head *eh, int key_hash) +{ + eh->head = eina_rbtree_inline_remove(eh->head, EINA_RBTREE_GET(el), EINA_RBTREE_CMP_NODE_CB(_eina_hash_key_rbtree_cmp_node), hash->key_cmp_cb); + if (el->begin == EINA_FALSE) free(el); + + if (!eh->head) + { + key_hash &= EINA_HASH_BUCKET_MASK; + + hash->buckets[key_hash] = eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET(eh), EINA_RBTREE_CMP_NODE_CB(_eina_hash_hash_rbtree_cmp_node), NULL); + free(eh); + } + + hash->population--; + + return EINA_TRUE; +} + /** - * Removes the entry identified by @p key and @p key_hash or @p data from the given + * Removes the entry identified by @p key and @p key_hash from the given * hash table. * - * If @p key is @c NULL, then @p data is used to find a match to - * remove. - * * @param hash The given hash table. - * @param key The key. Can be @c NULL. + * @param key The key. Cannot be @c NULL. * @param key_length Should be the length of @p key (don't forget to count '\\0' for string). - * @param key_hash The hash that always match the key. Ignored if @p key is @c NULL. - * @param data The data pointer to remove if @p key is @c NULL. - * Otherwise, not required and can be @c NULL. + * @param key_hash The hash that always match the key. * @return Will return EINA_FALSE if an error occured, and EINA_TRUE if every * thing goes fine. + * + * @note if you don't have the key_hash, use eina_hash_del_by_key() instead. + * @note if you don't have the key, use eina_hash_del_by_data() instead. */ EAPI Eina_Bool -eina_hash_del_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash, const void *data) +eina_hash_del_by_key_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash) { - Eina_Hash_El *el = NULL; + Eina_Hash_El *el; Eina_Hash_Head *eh; Eina_Hash_Tuple tuple; + if (!hash) return EINA_FALSE; + if (!key) return EINA_FALSE; + tuple.key = (void *) key; tuple.key_length = key_length; - tuple.data = (void *) data; + tuple.data = NULL; - if (!hash) return EINA_FALSE; - if (!key) el = _eina_hash_find_by_data(hash, data, &key_hash, &eh); - else el = _eina_hash_find_by_hash(hash, &tuple, key_hash, &eh); - + el = _eina_hash_find_by_hash(hash, &tuple, key_hash, &eh); if (!el) return EINA_FALSE; - if (data && el->tuple.data != data) return EINA_FALSE; + return _eina_hash_del_by_hash_el(hash, el, eh, key_hash); +} - eh->head = eina_rbtree_inline_remove(eh->head, EINA_RBTREE_GET(el), EINA_RBTREE_CMP_NODE_CB(_eina_hash_key_rbtree_cmp_node), hash->key_cmp_cb); - if (el->begin == EINA_FALSE) free(el); +/** + * Removes the entry identified by @p key from the given hash table. + * + * This version will calculate key length and hash by using functions + * provided to hash creation function. + * + * @param hash The given hash table. + * @param key The key. Cannot be @c NULL. + * @return Will return EINA_FALSE if an error occured, and EINA_TRUE if every + * thing goes fine. + * + * @note if you already have the key_hash, use eina_hash_del_by_key_hash() instead. + * @note if you don't have the key, use eina_hash_del_by_data() instead. + */ +EAPI Eina_Bool +eina_hash_del_by_key(Eina_Hash *hash, const void *key) +{ + int key_length, key_hash; - if (!eh->head) - { - key_hash &= EINA_HASH_BUCKET_MASK; + if (!hash) return EINA_FALSE; + if (!key) return EINA_FALSE; - hash->buckets[key_hash] = eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET(eh), EINA_RBTREE_CMP_NODE_CB(_eina_hash_hash_rbtree_cmp_node), NULL); - free(eh); - } + key_length = hash->key_length_cb(key); + key_hash = hash->key_hash_cb(key, key_length); + return eina_hash_del_by_key_hash(hash, key, key_length, key_hash); +} - hash->population--; +/** + * Removes the entry identified by @p data from the given hash table. + * + * This version is slow since there is no quick access to nodes based on data. + * + * @param hash The given hash table. + * @param data The data value to search and remove. + * @return Will return EINA_FALSE if an error occured, and EINA_TRUE if every + * thing goes fine. + * + * @note if you already have the key, use eina_hash_del_by_key() or eina_hash_del_by_key_hash() instead. + */ +EAPI Eina_Bool +eina_hash_del_by_data(Eina_Hash *hash, const void *data) +{ + Eina_Hash_El *el; + Eina_Hash_Head *eh; + int key_hash; - return EINA_TRUE; + if (!hash) return EINA_FALSE; + if (!data) return EINA_FALSE; + + el = _eina_hash_find_by_data(hash, data, &key_hash, &eh); + if (!el) return EINA_FALSE; + if (el->tuple.data != data) return EINA_FALSE; + return _eina_hash_del_by_hash_el(hash, el, eh, key_hash); } /** + * Removes the entry identified by @p key and @p key_hash or @p data from the given + * hash table. + * + * If @p key is @c NULL, then @p data is used to find a match to + * remove. + * + * @param hash The given hash table. + * @param key The key. Can be @c NULL. + * @param key_length Should be the length of @p key (don't forget to count '\\0' for string). + * @param key_hash The hash that always match the key. Ignored if @p key is @c NULL. + * @param data The data pointer to remove if @p key is @c NULL. + * Otherwise, not required and can be @c NULL. + * @return Will return EINA_FALSE if an error occured, and EINA_TRUE if every + * thing goes fine. + * + * @note if you know you already have the key, use eina_hash_del_by_key_hash(), + * if you know you don't have the key, use eina_hash_del_by_data() + * directly. + */ +EAPI Eina_Bool +eina_hash_del_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash, const void *data) +{ + if (key) return eina_hash_del_by_key_hash(hash, key, key_length, key_hash); + else return eina_hash_del_by_data(hash, data); +} + +/** * Removes the entry identified by @p key or @p data from the given * hash table. * @@ -818,21 +902,17 @@ * Otherwise, not required and can be @c NULL. * @return Will return EINA_FALSE if an error occured, and EINA_TRUE if every * thing goes fine. + * + * @note if you know you already have the key, use + * eina_hash_del_by_key() or eina_hash_del_by_key_hash(). If you + * know you don't have the key, use eina_hash_del_by_data() + * directly. */ EAPI Eina_Bool eina_hash_del(Eina_Hash *hash, const void *key, const void *data) { - int key_length = 0; - int hash_num = 0; /* XXX: shut up GCC, not really required */ - - if (!hash) return EINA_FALSE; - if (key) - { - key_length = hash->key_length_cb(key); - hash_num = hash->key_hash_cb(key, key_length); - } - - return eina_hash_del_by_hash(hash, key, key_length, hash_num, data); + if (key) return eina_hash_del_by_key(hash, key); + else return eina_hash_del_by_data(hash, data); } /** |
From: Enlightenment S. <no-...@en...> - 2009-02-27 16:32:26
|
Log: New macros, documentation and consistency for iterators and accessors. EINA_ITERATOR_FOREACH() and EINA_ACCESSOR_FOREACH() are new macros to help us forget about nasty C details (like cast to (void **)). Document most iterators and accessors. All iterators now set EINA_ERROR_OUT_OF_MEMORY if it's the case. Author: barbieri Date: 2009-02-27 08:32:22 -0800 (Fri, 27 Feb 2009) New Revision: 39267 Modified: trunk/eina/src/include/eina_accessor.h trunk/eina/src/include/eina_iterator.h trunk/eina/src/include/eina_list.h trunk/eina/src/lib/eina_hash.c trunk/eina/src/lib/eina_list.c trunk/eina/src/lib/eina_rbtree.c Modified: trunk/eina/src/include/eina_accessor.h =================================================================== --- trunk/eina/src/include/eina_accessor.h 2009-02-27 15:30:32 UTC (rev 39266) +++ trunk/eina/src/include/eina_accessor.h 2009-02-27 16:32:22 UTC (rev 39267) @@ -67,6 +67,55 @@ const void *fdata) EINA_ARG_NONNULL(1, 2); /** + * @def EINA_ACCESSOR_FOREACH + * @brief Macro to iterate over all elements easily. + * + * @param accessor The accessor to use. + * @param data Where to store * data, must be a pointer support getting + * its address since * eina_accessor_data_get() requires a pointer + * to pointer! + * + * This macro is a convenient way to loop over all elements in an + * accessor, very similar to EINA_LIST_FOREACH(). + * + * This macro can be used for freeing the data of a list, like in the + * following example. It has the same goal as the one documented in + * EINA_LIST_FOREACH(), but using accessors: + * + * @code + * Eina_List *list; + * Eina_Accessor *accessor; + * unsigned int i; + * char *data; + * + * // list is already filled, + * // its elements are just duplicated strings + * + * accessor = eina_list_accessor_new(list); + * EINA_ACCESSOR_FOREACH(accessor, i, data) + * free(data); + * eina_accessor_free(accessor); + * eina_list_free(list); + * @endcode + * + * @note if the datatype provides both iterators and accessors prefer + * to use iterators to iterate over, as they're likely to be more + * optimized for such task. + * + * @note this example is not optimal algorithm to release a list since + * it will walk the list twice, but it serves as an example. For + * optimized version use EINA_LIST_FREE() + * + * @warning unless explicitly stated in functions returning accessors, + * do not modify the accessed object while you walk it, in this + * example using lists, do not remove list nodes or you might + * crash! This is not a limitiation of accessors themselves, + * rather in the accessors implementations to keep them as simple + * and fast as possible. + */ +#define EINA_ACCESSOR_FOREACH(accessor, counter, data) for ((counter) = 0; eina_accessor_data_get((accessor), (counter), (void **)&(data)); (counter)++) + +/** * @} */ Modified: trunk/eina/src/include/eina_iterator.h =================================================================== --- trunk/eina/src/include/eina_iterator.h 2009-02-27 15:30:32 UTC (rev 39266) +++ trunk/eina/src/include/eina_iterator.h 2009-02-27 16:32:22 UTC (rev 39267) @@ -65,6 +65,50 @@ const void *fdata) EINA_ARG_NONNULL(1, 2); /** + * @def EINA_ITERATOR_FOREACH + * @brief Macro to iterate over all elements easily. + * + * @param iterator The iterator to use. + * @param data Where to store * data, must be a pointer support getting + * its address since * eina_iterator_next() requires a pointer + * to pointer! + * + * This macro is a convenient way to use iterators, very similar to + * EINA_LIST_FOREACH(). + * + * This macro can be used for freeing the data of a list, like in the + * following example. It has the same goal as the one documented in + * EINA_LIST_FOREACH(), but using iterators: + * + * @code + * Eina_List *list; + * Eina_Iterator *itr; + * char *data; + * + * // list is already filled, + * // its elements are just duplicated strings + * + * itr = eina_list_iterator_new(list); + * EINA_ITERATOR_FOREACH(itr, data) + * free(data); + * eina_iterator_free(itr); + * eina_list_free(list); + * @endcode + * + * @note this example is not optimal algorithm to release a list since + * it will walk the list twice, but it serves as an example. For + * optimized version use EINA_LIST_FREE() + * + * @warning unless explicitly stated in functions returning iterators, + * do not modify the iterated object while you walk it, in this + * example using lists, do not remove list nodes or you might + * crash! This is not a limitiation of iterators themselves, + * rather in the iterators implementations to keep them as simple + * and fast as possible. + */ +#define EINA_ITERATOR_FOREACH(itr, data) while (eina_iterator_next((itr), (void **)&(data))) + +/** * @} */ Modified: trunk/eina/src/include/eina_list.h =================================================================== --- trunk/eina/src/include/eina_list.h 2009-02-27 15:30:32 UTC (rev 39266) +++ trunk/eina/src/include/eina_list.h 2009-02-27 16:32:22 UTC (rev 39267) @@ -137,10 +137,16 @@ * * EINA_LIST_FOREACH(list, l, data) * free(data); + * eina_list_free(list); * @endcode * - * @warning do not delete list nodes, specially the current node, while - * iterating. If you wish to do so, use EINA_LIST_FOREACH_SAFE(). + * @note this example is not optimal algorithm to release a list since + * it will walk the list twice, but it serves as an example. For + * optimized version use EINA_LIST_FREE() + * + * @warning do not delete list nodes, specially the current node, + * while iterating. If you wish to do so, use + * EINA_LIST_FOREACH_SAFE(). */ #define EINA_LIST_FOREACH(list, l, data) for (l = list, data = eina_list_data_get(l); l; l = eina_list_next(l), data = eina_list_data_get(l)) @@ -171,10 +177,16 @@ * * EINA_LIST_REVERSE_FOREACH(list, l, data) * free(data); + * eina_list_free(list); * @endcode * - * @warning do not delete list nodes, specially the current node, while - * iterating. If you wish to do so, use EINA_LIST_REVERSE_FOREACH_SAFE(). + * @note this example is not optimal algorithm to release a list since + * it will walk the list twice, but it serves as an example. For + * optimized version use EINA_LIST_FREE() + * + * @warning do not delete list nodes, specially the current node, + * while iterating. If you wish to do so, use + * EINA_LIST_REVERSE_FOREACH_SAFE(). */ #define EINA_LIST_REVERSE_FOREACH(list, l, data) for (l = eina_list_last(list), data = eina_list_data_get(l); l; l = eina_list_prev(l), data = eina_list_data_get(l)) @@ -260,6 +272,24 @@ */ #define EINA_LIST_REVERSE_FOREACH_SAFE(list, l, l_prev, data) for (l = list, l_prev = eina_list_prev(l), data = eina_list_data_get(l); l; l = l_prev, l_prev = eina_list_prev(l), data = eina_list_data_get(l)) +/** + * Easy way to free the while list while being able to release its pointed data. + * + * @code + * Eina_List *list; + * char *data; + * + * // list is already filled, + * // its elements are just duplicated strings, + * + * EINA_LIST_FREE(list, data) + * free(data); + * @endcode + * + * If you do not need to release node data then use eina_list_free(). + * + * @see eina_list_free() + */ #define EINA_LIST_FREE(list, data) for (data = list ? eina_list_data_get(list) : NULL; list; list = eina_list_remove_list(list, list), data = list ? eina_list_data_get(list) : NULL) #include "eina_inline_list.x" Modified: trunk/eina/src/lib/eina_hash.c =================================================================== --- trunk/eina/src/lib/eina_hash.c 2009-02-27 15:30:32 UTC (rev 39266) +++ trunk/eina/src/lib/eina_hash.c 2009-02-27 16:32:22 UTC (rev 39267) @@ -277,7 +277,7 @@ Eina_Bool found = EINA_TRUE; it = eina_rbtree_iterator_prefix(eh->head); - while (eina_iterator_next(it, (void**) &el)) + EINA_ITERATOR_FOREACH(it, el) { if (el->tuple.data == data->data) { @@ -1293,6 +1293,25 @@ eina_iterator_free(it); } +/** + * @brief Returned a new iterator asociated to hash data. + * + * @param hash The hash. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * hash. If @p hash is not populated, this function still returns a + * valid iterator that will always return false on + * eina_iterator_next(), thus keeping API sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the hash structure changes then the iterator becomes + * invalid! That is, if you add or remove items this iterator + * behavior is undefined and your program may crash! + */ EAPI Eina_Iterator * eina_hash_iterator_data_new(const Eina_Hash *hash) { @@ -1301,8 +1320,12 @@ EINA_MAGIC_CHECK_HASH(hash); EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + eina_error_set(0); it = calloc(1, sizeof (Eina_Iterator_Hash)); - if (!it) return NULL; + if (!it) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } it->hash = hash; it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_data_get_content); @@ -1317,6 +1340,25 @@ return &it->iterator; } +/** + * @brief Returned a new iterator asociated to hash keys. + * + * @param hash The hash. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * hash. If @p hash is not populated, this function still returns a + * valid iterator that will always return false on + * eina_iterator_next(), thus keeping API sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the hash structure changes then the iterator becomes + * invalid! That is, if you add or remove items this iterator + * behavior is undefined and your program may crash! + */ EAPI Eina_Iterator * eina_hash_iterator_key_new(const Eina_Hash *hash) { @@ -1325,8 +1367,12 @@ EINA_MAGIC_CHECK_HASH(hash); EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + eina_error_set(0); it = calloc(1, sizeof (Eina_Iterator_Hash)); - if (!it) return NULL; + if (!it) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } it->hash = hash; it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_key_get_content); @@ -1341,6 +1387,28 @@ return &it->iterator; } +/** + * @brief Returned a new iterator asociated to hash keys and data. + * + * @param hash The hash. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * hash. If @p hash is not populated, this function still returns a + * valid iterator that will always return false on + * eina_iterator_next(), thus keeping API sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @note iterator data will provide values as Eina_Hash_Tuple that should not + * be modified! + * + * @warning if the hash structure changes then the iterator becomes + * invalid! That is, if you add or remove items this iterator + * behavior is undefined and your program may crash! + */ EAPI Eina_Iterator * eina_hash_iterator_tuple_new(const Eina_Hash *hash) { @@ -1349,8 +1417,12 @@ EINA_MAGIC_CHECK_HASH(hash); EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + eina_error_set(0); it = calloc(1, sizeof (Eina_Iterator_Hash)); - if (!it) return NULL; + if (!it) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } it->hash = hash; it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_tuple_get_content); Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2009-02-27 15:30:32 UTC (rev 39266) +++ trunk/eina/src/lib/eina_list.c 2009-02-27 16:32:22 UTC (rev 39267) @@ -1555,11 +1555,19 @@ * @param list The list. * @return A new iterator. * - * This function returns a newly allocated iterator associated to - * @p list. If @p list is @c NULL or the count member of @p list is - * less or equal than 0, this function returns NULL. If the memory can - * not be allocated, NULL is returned and #EINA_ERROR_OUT_OF_MEMORY is - * set. Otherwise, a valid iterator is returned. + * This function returns a newly allocated iterator associated to @p + * list. If @p list is @c NULL or the count member of @p list is less + * or equal than 0, this function still returns a valid iterator that + * will always return false on eina_iterator_next(), thus keeping API + * sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the list structure changes then the iterator becomes + * invalid! That is, if you add or remove nodes this iterator + * behavior is undefined and your program may crash! */ EAPI Eina_Iterator * eina_list_iterator_new(const Eina_List *list) Modified: trunk/eina/src/lib/eina_rbtree.c =================================================================== --- trunk/eina/src/lib/eina_rbtree.c 2009-02-27 15:30:32 UTC (rev 39266) +++ trunk/eina/src/lib/eina_rbtree.c 2009-02-27 16:32:22 UTC (rev 39267) @@ -62,8 +62,12 @@ { Eina_Iterator_Rbtree_List *new; + eina_error_set(0); new = malloc(sizeof (Eina_Iterator_Rbtree_List)); - if (!new) return NULL; + if (!new) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } new->tree = (Eina_Rbtree*) tree; new->dir = EINA_RBTREE_RIGHT; @@ -162,8 +166,12 @@ Eina_Iterator_Rbtree_List *first; Eina_Iterator_Rbtree *it; + eina_error_set(0); it = calloc(1, sizeof (Eina_Iterator_Rbtree)); - if (!it) return NULL; + if (!it) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } it->stack = eina_array_new(8); if (!it->stack) goto on_error; @@ -437,18 +445,75 @@ return root; } +/** + * @brief Returned a new prefix iterator asociated to a rbtree. + * + * @param root The root of rbtree. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * root. It will iterate the tree using prefix walk. If @p root is @c + * NULL, this function still returns a valid iterator that will always + * return false on eina_iterator_next(), thus keeping API sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the rbtree structure changes then the iterator becomes + * invalid! That is, if you add or remove nodes this iterator + * behavior is undefined and your program may crash! + */ EAPI Eina_Iterator * eina_rbtree_iterator_prefix(const Eina_Rbtree *root) { return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_PREFIX_MASK); } +/** + * @brief Returned a new prefix iterator asociated to a rbtree. + * + * @param root The root of rbtree. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * root. It will iterate the tree using infix walk. If @p root is @c + * NULL, this function still returns a valid iterator that will always + * return false on eina_iterator_next(), thus keeping API sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the rbtree structure changes then the iterator becomes + * invalid! That is, if you add or remove nodes this iterator + * behavior is undefined and your program may crash! + */ EAPI Eina_Iterator * eina_rbtree_iterator_infix(const Eina_Rbtree *root) { return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_INFIX_MASK); } +/** + * @brief Returned a new prefix iterator asociated to a rbtree. + * + * @param root The root of rbtree. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * root. It will iterate the tree using postfix walk. If @p root is @c + * NULL, this function still returns a valid iterator that will always + * return false on eina_iterator_next(), thus keeping API sane. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the rbtree structure changes then the iterator becomes + * invalid! That is, if you add or remove nodes this iterator + * behavior is undefined and your program may crash! + */ EAPI Eina_Iterator * eina_rbtree_iterator_postfix(const Eina_Rbtree *root) { |
From: Enlightenment S. <no-...@en...> - 2009-03-13 11:33:06
|
Log: inlist: add count. Author: barbieri Date: 2009-03-13 04:32:56 -0700 (Fri, 13 Mar 2009) New Revision: 39465 Modified: trunk/eina/src/include/eina_inlist.h trunk/eina/src/lib/eina_inlist.c Modified: trunk/eina/src/include/eina_inlist.h =================================================================== --- trunk/eina/src/include/eina_inlist.h 2009-03-13 10:53:07 UTC (rev 39464) +++ trunk/eina/src/include/eina_inlist.h 2009-03-13 11:32:56 UTC (rev 39465) @@ -47,6 +47,7 @@ EAPI Eina_Inlist * eina_inlist_find(Eina_Inlist *in_list, Eina_Inlist *in_item) EINA_ARG_NONNULL(2) EINA_WARN_UNUSED_RESULT; EAPI Eina_Inlist * eina_inlist_promote(Eina_Inlist *list, Eina_Inlist *item) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT; EAPI Eina_Inlist * eina_inlist_demote(Eina_Inlist *list, Eina_Inlist *item) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT; +EAPI unsigned int eina_inlist_count(const Eina_Inlist *list) EINA_WARN_UNUSED_RESULT; EAPI Eina_Iterator *eina_inlist_iterator_new(const Eina_Inlist *in_list) EINA_MALLOC EINA_WARN_UNUSED_RESULT; EAPI Eina_Accessor *eina_inlist_accessor_new(const Eina_Inlist *in_list) EINA_MALLOC EINA_WARN_UNUSED_RESULT; Modified: trunk/eina/src/lib/eina_inlist.c =================================================================== --- trunk/eina/src/lib/eina_inlist.c 2009-03-13 10:53:07 UTC (rev 39464) +++ trunk/eina/src/lib/eina_inlist.c 2009-03-13 11:32:56 UTC (rev 39465) @@ -347,6 +347,31 @@ return NULL; } +/** + * @brief Get the count of the number of items in a list. + * + * @param list The list whose count to return. + * @return The number of members in the list. + * + * This function returns how many members @p list contains. If the + * list is @c NULL, 0 is returned. + * + * @warning This is an order-N operation and so the time will depend + * on the number of elements on the list, that is, it might become + * slow for big lists! + */ +EAPI unsigned int +eina_inlist_count(const Eina_Inlist *list) +{ + const Eina_Inlist *l; + unsigned int i = 0; + + for (l = list; l; l = l->next) + i++; + + return i; +} + EAPI Eina_Iterator * eina_inlist_iterator_new(const Eina_Inlist *list) { |
From: Enlightenment S. <no-...@en...> - 2009-03-17 12:52:45
|
Log: fix docs and add clone and reversed iterator calls. * docs: be clear if it's a copy or in-place. * clone: add some apis to create a copy while operates, sort should do the same. * reversed iterator: new call to walk the list reversed, will make life easier in some cases. Author: barbieri Date: 2009-03-17 05:52:38 -0700 (Tue, 17 Mar 2009) New Revision: 39515 Modified: trunk/eina/src/include/eina_list.h trunk/eina/src/lib/eina_list.c Modified: trunk/eina/src/include/eina_list.h =================================================================== --- trunk/eina/src/include/eina_list.h 2009-03-17 01:40:50 UTC (rev 39514) +++ trunk/eina/src/include/eina_list.h 2009-03-17 12:52:38 UTC (rev 39515) @@ -94,6 +94,8 @@ EAPI void *eina_list_nth(const Eina_List *list, unsigned int n) EINA_PURE EINA_WARN_UNUSED_RESULT; EAPI Eina_List *eina_list_nth_list (const Eina_List *list, unsigned int n) EINA_PURE EINA_WARN_UNUSED_RESULT; EAPI Eina_List *eina_list_reverse (Eina_List *list) EINA_WARN_UNUSED_RESULT; +EAPI Eina_List *eina_list_reverse_clone(const Eina_List *list) EINA_WARN_UNUSED_RESULT; +EAPI Eina_List *eina_list_clone(const Eina_List *list) EINA_WARN_UNUSED_RESULT; EAPI Eina_List *eina_list_sort (Eina_List *list, unsigned int size, Eina_Compare_Cb func) EINA_ARG_NONNULL(3) EINA_WARN_UNUSED_RESULT; EAPI Eina_List *eina_list_merge (Eina_List *left, Eina_List *right) EINA_WARN_UNUSED_RESULT; EAPI Eina_List *eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func) EINA_ARG_NONNULL(3) EINA_WARN_UNUSED_RESULT; Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2009-03-17 01:40:50 UTC (rev 39514) +++ trunk/eina/src/lib/eina_list.c 2009-03-17 12:52:38 UTC (rev 39515) @@ -244,6 +244,19 @@ return EINA_TRUE; } +static Eina_Bool +eina_list_iterator_prev(Eina_Iterator_List *it, void **data) +{ + EINA_MAGIC_CHECK_LIST_ITERATOR(it); + + if (it->current == NULL) return EINA_FALSE; + if (data) *data = eina_list_data_get(it->current); + + it->current = eina_list_prev(it->current); + + return EINA_TRUE; +} + static Eina_List * eina_list_iterator_get_container(Eina_Iterator_List *it) { @@ -1225,11 +1238,17 @@ * @brief Reverse all the elements in the list. * * @param list The list to reverse. - * @return The list after it has been reversed. + * @return The list head after it has been reversed. * * This function reverses the order of all elements in @p list, so the * last member is now first, and so on. If @p list is @c NULL, this * functon returns @c NULL. + * + * @note @b in-place: this will change the given list, so you should + * now point to the new list head that is returned by this function. + * + * @see eina_list_reverse_clone() + * @see eina_list_iterator_reversed_new() */ EAPI Eina_List * eina_list_reverse(Eina_List *list) @@ -1258,13 +1277,80 @@ } /** + * @brief Clone (copy) all the elements in the list in reverse order. + * + * @param list The list to reverse. + * @return The new list that has been reversed. + * + * This function reverses the order of all elements in @p list, so the + * last member is now first, and so on. If @p list is @c NULL, this + * functon returns @c NULL. This returns a copy of the given list. + * + * @note @b copy: this will copy the list and you should then + * eina_list_free() when it is not required anymore. + * + * @see eina_list_reverse() + * @see eina_list_clone() + */ +EAPI Eina_List * +eina_list_reverse_clone(const Eina_List *list) +{ + const Eina_List *l; + Eina_List *clone; + void *data; + + if (!list) return NULL; + + EINA_MAGIC_CHECK_LIST(list); + + clone = NULL; + EINA_LIST_FOREACH(list, l, data) + clone = eina_list_prepend(clone, data); + + return clone; +} + +/** + * @brief Clone (copy) all the elements in the list in exact order. + * + * @param list The list to clone. + * @return The new list that has been cloned. + * + * This function clone in order of all elements in @p list. If @p list + * is @c NULL, this functon returns @c NULL. This returns a copy of + * the given list. + * + * @note @b copy: this will copy the list and you should then + * eina_list_free() when it is not required anymore. + * + * @see eina_list_reverse_clone() + */ +EAPI Eina_List * +eina_list_clone(const Eina_List *list) +{ + const Eina_List *l; + Eina_List *clone; + void *data; + + if (!list) return NULL; + + EINA_MAGIC_CHECK_LIST(list); + + clone = NULL; + EINA_LIST_FOREACH(list, l, data) + clone = eina_list_append(clone, data); + + return clone; +} + +/** * @brief Sort a list according to the ordering func will return. * * @param list The list handle to sort. * @param size The length of the list to sort. * @param func A function pointer that can handle comparing the list data * nodes. - * @return A new sorted list. + * @return the new head of list. * * This function sorts @p list. @p size if the number of the first * element to sort. If @p size is 0 or greater than the number of @@ -1272,6 +1358,9 @@ * compare two elements of @p list. If @p list or @p func are @c NULL, * this function returns @c NULL. * + * @note @b in-place: this will change the given list, so you should + * now point to the new list head that is returned by this function. + * * Example: * @code * int @@ -1595,6 +1684,53 @@ } /** + * @brief Returned a new reversed iterator asociated to a list. + * + * @param list The list. + * @return A new iterator. + * + * This function returns a newly allocated iterator associated to @p + * list. If @p list is @c NULL or the count member of @p list is less + * or equal than 0, this function still returns a valid iterator that + * will always return false on eina_iterator_next(), thus keeping API + * sane. + * + * Unlike eina_list_iterator_new(), this will walk the list backwards. + * + * If the memory can not be allocated, NULL is returned and + * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is + * returned. + * + * @warning if the list structure changes then the iterator becomes + * invalid! That is, if you add or remove nodes this iterator + * behavior is undefined and your program may crash! + */ +EAPI Eina_Iterator * +eina_list_iterator_reversed_new(const Eina_List *list) +{ + Eina_Iterator_List *it; + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_List)); + if (!it) { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->head = eina_list_last(list); + it->current = it->head; + + it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_prev); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(eina_list_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free); + + return &it->iterator; +} + +/** * @brief Returned a new accessor asociated to a list. * * @param list The list. |
From: Enlightenment S. <no-...@en...> - 2009-04-06 12:41:54
|
Log: export vargs version of eina_error_print(). Author: barbieri Date: 2009-04-06 05:41:50 -0700 (Mon, 06 Apr 2009) New Revision: 39879 Modified: trunk/eina/src/include/eina_error.h trunk/eina/src/lib/eina_error.c Modified: trunk/eina/src/include/eina_error.h =================================================================== --- trunk/eina/src/include/eina_error.h 2009-04-06 11:21:28 UTC (rev 39878) +++ trunk/eina/src/include/eina_error.h 2009-04-06 12:41:50 UTC (rev 39879) @@ -117,6 +117,9 @@ EAPI const char * eina_error_msg_get(Eina_Error error) EINA_PURE; EAPI void eina_error_print(Eina_Error_Level level, const char *file, const char *function, int line, const char *fmt, ...) EINA_ARG_NONNULL(2, 3, 5) EINA_PRINTF(5, 6); +EAPI void eina_error_vprint(Eina_Error_Level level, const char *file, + const char *fnc, int line, const char *fmt, va_list args) EINA_ARG_NONNULL(2, 3, 5); + EAPI void eina_error_print_cb_stdout(Eina_Error_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); Modified: trunk/eina/src/lib/eina_error.c =================================================================== --- trunk/eina/src/lib/eina_error.c 2009-04-06 11:21:28 UTC (rev 39878) +++ trunk/eina/src/lib/eina_error.c 2009-04-06 12:41:50 UTC (rev 39879) @@ -700,6 +700,21 @@ if (getenv("EINA_ERROR_ABORT")) abort(); } +EAPI void eina_error_vprint(Eina_Error_Level level, const char *file, + const char *fnc, int line, const char *fmt, va_list args) +{ + if (level > _error_level) + return; + + EINA_SAFETY_ON_NULL_RETURN(file); + EINA_SAFETY_ON_NULL_RETURN(fnc); + EINA_SAFETY_ON_NULL_RETURN(fmt); + + _print_cb(level, file, fnc, line, fmt, _print_cb_data, args); + + if (getenv("EINA_ERROR_ABORT")) abort(); +} + /** * @brief Print callback that sends the error message to stdout. * |
From: Enlightenment S. <no-...@en...> - 2009-05-06 04:11:04
|
Log: enable adding just part of a string. this allows us to add stringshare from a larger buffer that cannot be modified. Author: barbieri Date: 2009-05-05 21:11:01 -0700 (Tue, 05 May 2009) New Revision: 40516 Modified: trunk/eina/src/include/eina_stringshare.h trunk/eina/src/lib/eina_stringshare.c Modified: trunk/eina/src/include/eina_stringshare.h =================================================================== --- trunk/eina/src/include/eina_stringshare.h 2009-05-05 21:48:50 UTC (rev 40515) +++ trunk/eina/src/include/eina_stringshare.h 2009-05-06 04:11:01 UTC (rev 40516) @@ -67,6 +67,7 @@ EAPI int eina_stringshare_init(void); EAPI int eina_stringshare_shutdown(void); +EAPI const char *eina_stringshare_add_length(const char *str, unsigned int slen) EINA_WARN_UNUSED_RESULT; EAPI const char *eina_stringshare_add(const char *str) EINA_WARN_UNUSED_RESULT; EAPI const char *eina_stringshare_ref(const char *str); EAPI void eina_stringshare_del(const char *str); Modified: trunk/eina/src/lib/eina_stringshare.c =================================================================== --- trunk/eina/src/lib/eina_stringshare.c 2009-05-05 21:48:50 UTC (rev 40515) +++ trunk/eina/src/lib/eina_stringshare.c 2009-05-06 04:11:01 UTC (rev 40516) @@ -350,7 +350,7 @@ static inline int _eina_stringshare_small_cmp(const Eina_Stringshare_Small_Bucket *bucket, int i, const char *pstr, unsigned char plength) { - const unsigned char cur_plength = bucket->lengths[i] - 1; + const unsigned char cur_plength = bucket->lengths[i]; const char *cur_pstr; if (cur_plength > plength) @@ -380,7 +380,7 @@ _eina_stringshare_small_bucket_find(const Eina_Stringshare_Small_Bucket *bucket, const char *str, unsigned char length, int *index) { const char *pstr = str + 1; /* skip first letter, it's always the same */ - unsigned char plength = length - 1; + unsigned char plength = length; int i, low, high; if (bucket->count == 0) @@ -456,6 +456,7 @@ { Eina_Stringshare_Small_Bucket *bucket = *p_bucket; int todo, off; + char *snew; if (!bucket) { @@ -474,18 +475,20 @@ return NULL; } - str = strdup(str); - if (!str) + snew = malloc(length + 1); + if (!snew) { eina_error_set(EINA_ERROR_OUT_OF_MEMORY); return NULL; } + memcpy(snew, str, length); + snew[length] = '\0'; off = index + 1; todo = bucket->count - index; if (todo > 0) { - memmove((void *)(bucket->strings + off), bucket->strings + index, + memmove((void *)(bucket->strings + off), bucket->strings + index, todo * sizeof(bucket->strings[0])); memmove(bucket->lengths + off, bucket->lengths + index, todo * sizeof(bucket->lengths[0])); @@ -493,12 +496,12 @@ todo * sizeof(bucket->references[0])); } - bucket->strings[index] = str; + bucket->strings[index] = snew; bucket->lengths[index] = length; bucket->references[index] = 1; bucket->count++; - return str; + return snew; } static void @@ -635,6 +638,7 @@ node->references = 1; node->length = slen; memcpy(node->str, str, slen); + node->str[slen] = '\0'; } static Eina_Stringshare_Head * @@ -643,7 +647,7 @@ Eina_Stringshare_Head *head, t; const size_t head_size = (char *)&(t.builtin_node.str) - (char *)&t; - head = malloc(head_size + slen); + head = malloc(head_size + slen + 1); if (!head) eina_error_set(EINA_ERROR_OUT_OF_MEMORY); @@ -756,7 +760,7 @@ Eina_Stringshare_Node *node, t; const size_t node_size = (char *)&(t.str) - (char *)&t; - node = malloc(node_size + slen); + node = malloc(node_size + slen + 1); if (!node) eina_error_set(EINA_ERROR_OUT_OF_MEMORY); @@ -885,6 +889,7 @@ * @brief Retrieve an instance of a string for use in a program. * * @param str The string to retrieve an instance of. + * @param slen The string size (<= strlen(str)). * @return A pointer to an instance of the string on success. * @c NULL on failure. * @@ -894,24 +899,24 @@ * it is added to the strings to be searched and a duplicated string * of @p str is returned. * + * This function does not check string size, but uses the give the + * exact given size. This can be used to stringshare part of a larger + * buffer or substring. + * * @note it's not possible to have more than 65k references or strings * bigger than 65k since we use 'unsigned short' to save space. + * + * @see eina_stringshare_add() */ EAPI const char * -eina_stringshare_add(const char *str) +eina_stringshare_add_length(const char *str, unsigned int slen) { Eina_Stringshare_Head **p_bucket, *ed; Eina_Stringshare_Node *el; - int hash_num, slen, hash; + int hash_num, hash; if (!str) return NULL; - if (str[0] == '\0') slen = 0; - else if (str[1] == '\0') slen = 1; - else if (str[2] == '\0') slen = 2; - else if (str[3] == '\0') slen = 3; - else slen = 3 + (int)strlen(str + 3); - _eina_stringshare_population_add(slen); if (slen == 0) @@ -921,8 +926,6 @@ else if (slen < 4) return _eina_stringshare_small_add(str, slen); - slen++; /* everything else need to account '\0' */ - hash = eina_hash_superfast(str, slen); hash_num = hash & 0xFF; hash = (hash >> 8) & EINA_STRINGSHARE_MASK; @@ -954,6 +957,44 @@ return el->str; } +/** + * @brief Retrieve an instance of a string for use in a program. + * + * @param str The NULL terminated string to retrieve an instance of. + * @return A pointer to an instance of the string on success. + * @c NULL on failure. + * + * This function retrieves an instance of @p str. If @p str is + * @c NULL, then @c NULL is returned. If @p str is already stored, it + * is just returned and its reference counter is increased. Otherwise + * it is added to the strings to be searched and a duplicated string + * of @p str is returned. + * + * The string @a str must be NULL terminated ('\0') and its full + * length will be used. To use part of the string or non-null + * terminated, use eina_stringshare_add_length() instead. + * + * @note it's not possible to have more than 65k references or strings + * bigger than 65k since we use 'unsigned short' to save space. + * + * @see eina_stringshare_add_length() + */ +EAPI const char * +eina_stringshare_add(const char *str) +{ + int slen; + + if (!str) return NULL; + + if (str[0] == '\0') slen = 0; + else if (str[1] == '\0') slen = 1; + else if (str[2] == '\0') slen = 2; + else if (str[3] == '\0') slen = 3; + else slen = 3 + (int)strlen(str + 3); + + return eina_stringshare_add_length(str, slen); +} + static Eina_Stringshare_Node * _eina_stringshare_node_from_str(const char *str) { @@ -1058,7 +1099,7 @@ } node->references = 0; - slen = node->length; /* already includes '\0' */ + slen = node->length; hash = eina_hash_superfast(str, slen); hash_num = hash & 0xFF; @@ -1116,7 +1157,7 @@ if (str[3] == '\0') return 3; node = _eina_stringshare_node_from_str(str); - return node->length - 1; + return node->length; } struct dumpinfo |
From: Enlightenment S. <no-...@en...> - 2009-08-06 19:01:59
|
Log: API BREAK: eina_list_search_sorted_near_list() gets one more parameter. This should not impact anybody, at least in SVN I got no hits for this function. The new parameter contains the result of the last call to func(), so we can know if the node is smaller, bigger or exactly the requested value and don't need to call func() on node to know for sure. Author: barbieri Date: 2009-08-06 12:01:47 -0700 (Thu, 06 Aug 2009) New Revision: 41623 Modified: trunk/eina/src/include/eina_list.h trunk/eina/src/lib/eina_list.c Modified: trunk/eina/src/include/eina_list.h =================================================================== --- trunk/eina/src/include/eina_list.h 2009-08-06 18:35:53 UTC (rev 41622) +++ trunk/eina/src/include/eina_list.h 2009-08-06 19:01:47 UTC (rev 41623) @@ -100,7 +100,7 @@ EAPI Eina_List *eina_list_merge (Eina_List *left, Eina_List *right) EINA_WARN_UNUSED_RESULT; EAPI Eina_List *eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func) EINA_ARG_NONNULL(3) EINA_WARN_UNUSED_RESULT; -EAPI Eina_List *eina_list_search_sorted_near_list(const Eina_List *list, Eina_Compare_Cb func, const void *data); +EAPI Eina_List *eina_list_search_sorted_near_list(const Eina_List *list, Eina_Compare_Cb func, const void *data, int *result_cmp); EAPI Eina_List *eina_list_search_sorted_list(const Eina_List *list, Eina_Compare_Cb func, const void *data); EAPI void *eina_list_search_sorted(const Eina_List *list, Eina_Compare_Cb func, const void *data); EAPI Eina_List *eina_list_search_unsorted_list(const Eina_List *list, Eina_Compare_Cb func, const void *data); Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2009-08-06 18:35:53 UTC (rev 41622) +++ trunk/eina/src/lib/eina_list.c 2009-08-06 19:01:47 UTC (rev 41623) @@ -1678,6 +1678,11 @@ * @param list The list to search for data, @b must be sorted. * @param func A function pointer that can handle comparing the list data nodes. * @param data reference value to search. + * @param result_cmp if provided returns the result of + * func(node->data, data) node being the last (returned) node. If node + * was found (exact match), then it is 0. If returned node is smaller + * than requested data, it is less than 0 and if it's bigger it's + * greater than 0. It is the last value returned by func(). * @return the nearest node, NULL if not found. * * This can be used to check if some value is inside the list and get @@ -1701,42 +1706,50 @@ * @see eina_list_sorted_merge() */ EAPI Eina_List * -eina_list_search_sorted_near_list(const Eina_List *list, Eina_Compare_Cb func, const void *data) +eina_list_search_sorted_near_list(const Eina_List *list, Eina_Compare_Cb func, const void *data, int *result_cmp) { const Eina_List *ct; void *d; unsigned int inf, sup, cur, tmp; int part; - if (!list) return NULL; + if (!list) + { + if (result_cmp) *result_cmp = 0; + return NULL; + } inf = 0; - sup = eina_list_count(list) ; + sup = list->accounting->count; cur = sup >> 1; - ct = eina_list_nth_list(list, cur); - d = eina_list_data_get(ct); + for (tmp = 0, ct = list; tmp != cur; tmp++, ct = ct->next); + d = ct->data; + while ((part = func(d, data))) { if (inf == sup || (part < 0 && inf == cur) || (part > 0 && sup == cur)) - return (Eina_List*) ct; + goto end; + + tmp = (sup + inf) >> 1; if (part < 0) - inf = (sup + inf) >> 1; + inf = tmp; else - sup = (sup + inf) >> 1; + sup = tmp; /* Faster to move directly from where we are to the new position than using eina_list_nth_list. */ - tmp = (sup + inf) >> 1; if (tmp < cur) - for (; cur != tmp; cur--, ct = eina_list_prev(ct)) + for (; cur != tmp; cur--, ct = ct->prev) ; else - for (; cur != tmp; cur++, ct = eina_list_next(ct)) + for (; cur != tmp; cur++, ct = ct->next) ; - d = eina_list_data_get(ct); + d = ct->data; } + end: + if (result_cmp) *result_cmp = part; return (Eina_List*) ct; } @@ -1772,11 +1785,12 @@ { Eina_List *lnear; void *d; + int cmp; - lnear = eina_list_search_sorted_near_list(list, func, data); + lnear = eina_list_search_sorted_near_list(list, func, data, &cmp); if (!lnear) return NULL; d = eina_list_data_get(lnear); - if (!func(d, data)) + if (cmp == 0) return lnear; return NULL; } |
From: Enlightenment S. <no-...@en...> - 2009-09-02 23:07:13
|
Log: loggify eina_module, adding couple of debug info. Author: barbieri Date: 2009-09-02 16:06:55 -0700 (Wed, 02 Sep 2009) New Revision: 42194 Modified: trunk/eina/src/include/eina_private.h trunk/eina/src/lib/eina_module.c Modified: trunk/eina/src/include/eina_private.h =================================================================== --- trunk/eina/src/include/eina_private.h 2009-09-02 22:39:41 UTC (rev 42193) +++ trunk/eina/src/include/eina_private.h 2009-09-02 23:06:55 UTC (rev 42194) @@ -49,6 +49,8 @@ #define READBUFSIZ 65536 +#define EINA_LOG_COLOR_DEFAULT "\033[36m" + /* eina magic types */ #define EINA_MAGIC_STRINGSHARE 0x98761234 #define EINA_MAGIC_STRINGSHARE_NODE 0x98761235 Modified: trunk/eina/src/lib/eina_module.c =================================================================== --- trunk/eina/src/lib/eina_module.c 2009-09-02 22:39:41 UTC (rev 42193) +++ trunk/eina/src/lib/eina_module.c 2009-09-02 23:06:55 UTC (rev 42194) @@ -58,6 +58,7 @@ #include "eina_error.h" #include "eina_module.h" #include "eina_file.h" +#include "eina_log.h" /*============================================================================* * Local * @@ -67,6 +68,11 @@ * @cond LOCAL */ +static int EINA_MODULE_LOG_DOM = -1; +#define ERR(...) EINA_LOG_DOM_ERR(EINA_MODULE_LOG_DOM, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(EINA_MODULE_LOG_DOM, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(EINA_MODULE_LOG_DOM, __VA_ARGS__) + #if defined(_WIN32) || defined(__CYGWIN__) # define MODULE_EXTENSION ".dll" #else @@ -118,9 +124,9 @@ size_t length; length = strlen(name); - if (length < strlen(MODULE_EXTENSION) + 1) /* x.so */ + if (length < sizeof(MODULE_EXTENSION)) /* x.so */ return; - if (!strcmp(name + length - strlen(MODULE_EXTENSION), + if (!strcmp(name + length - sizeof(MODULE_EXTENSION) + 1, MODULE_EXTENSION)) { char *file; @@ -203,9 +209,25 @@ if (_eina_module_count != 1) goto end_init; + if (!eina_log_init()) + { + fprintf(stderr, "Could not initialize eina logging module.\n"); + return 0; + } + + EINA_MODULE_LOG_DOM = eina_log_domain_register + ("eina_module", EINA_LOG_COLOR_DEFAULT); + if (EINA_MODULE_LOG_DOM < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_module\n"); + eina_log_shutdown(); + return 0; + } + if (!eina_error_init()) { - fprintf(stderr, "Could not initialize eina error module.\n"); + ERR("Could not initialize eina error module.\n"); + eina_log_shutdown(); return 0; } @@ -243,6 +265,10 @@ * delete the list of modules here */ + eina_log_domain_unregister(EINA_MODULE_LOG_DOM); + EINA_MODULE_LOG_DOM = -1; + eina_log_shutdown(); + end_shutdown: return _eina_module_count; } @@ -274,6 +300,7 @@ m->file = strdup(file); m->ref = 0; m->handle = NULL; + DBG("m=%p, file=%s\n", m, file); return m; } @@ -293,6 +320,8 @@ { EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + DBG("m=%p, handle=%p, file=%s, refs=%d\n", m, m->handle, m->file, m->ref); + if (m->handle) { if (eina_module_unload(m) == EINA_FALSE) @@ -330,13 +359,14 @@ EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + DBG("m=%p, handle=%p, file=%s, refs=%d\n", m, m->handle, m->file, m->ref); + if (m->handle) goto loaded; dl_handle = dlopen(m->file, RTLD_NOW); if (!dl_handle) { - EINA_ERROR_PDBG("could not dlopen(\"%s\", RTLD_NOW): %s\n", - m->file, dlerror()); + WRN("could not dlopen(\"%s\", RTLD_NOW): %s\n", m->file, dlerror()); eina_error_set(EINA_ERROR_WRONG_MODULE); return EINA_FALSE; } @@ -347,13 +377,17 @@ if ((*initcall)() == EINA_TRUE) goto ok; + WRN("could not find eina's entry symbol %s inside module %s\n", + EINA_MODULE_SYMBOL_INIT, m->file); eina_error_set(EINA_ERROR_MODULE_INIT_FAILED); dlclose(dl_handle); return EINA_FALSE; ok: + DBG("successfully loaded %s", m->file); m->handle = dl_handle; loaded: m->ref++; + DBG("ref %d", m->ref); eina_error_set(0); return EINA_TRUE; @@ -378,6 +412,8 @@ Eina_Module_Shutdown *shut; EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + DBG("m=%p, handle=%p, file=%s, refs=%d\n", m, m->handle, m->file, m->ref); + m->ref--; if (!m->ref) { @@ -386,6 +422,7 @@ (*shut)(); dlclose(m->handle); m->handle = NULL; + DBG("unloaded module %s\n", m->file); return EINA_TRUE; } return EINA_FALSE; @@ -534,7 +571,7 @@ unsigned int i; EINA_SAFETY_ON_NULL_RETURN(array); - + DBG("array %p, count %u\n", array, array->count); EINA_ARRAY_ITER_NEXT(array, i, m, iterator) eina_module_load(m); } @@ -550,7 +587,7 @@ unsigned int i; EINA_SAFETY_ON_NULL_RETURN(array); - + DBG("array %p, count %u\n", array, array->count); EINA_ARRAY_ITER_NEXT(array, i, m, iterator) eina_module_unload(m); } @@ -566,7 +603,7 @@ unsigned int i; EINA_SAFETY_ON_NULL_RETURN(array); - + DBG("array %p, count %u\n", array, array->count); EINA_ARRAY_ITER_NEXT(array, i, m, iterator) eina_module_free(m); |
From: Enlightenment S. <no-...@en...> - 2009-09-02 23:28:11
|
Log: eina_log improvements: docs, micro optimizations and stderr logging by default. * more docs. * do not getenv("EINA_LOG_ABORT") everytime, just at init. * EINA_UNLIKELY() in some critical paths (not that big impact anyway) * eina_log_print_cb_stderr() and use it by default. Author: barbieri Date: 2009-09-02 16:28:00 -0700 (Wed, 02 Sep 2009) New Revision: 42196 Modified: trunk/eina/src/include/eina_log.h trunk/eina/src/lib/eina_log.c Modified: trunk/eina/src/include/eina_log.h =================================================================== --- trunk/eina/src/include/eina_log.h 2009-09-02 23:11:22 UTC (rev 42195) +++ trunk/eina/src/include/eina_log.h 2009-09-02 23:28:00 UTC (rev 42196) @@ -191,6 +191,7 @@ EAPI void eina_log_print(int domain, Eina_Log_Level level, const char *file, const char *function, int line, const char *fmt, ...) EINA_ARG_NONNULL(2, 3, 5); EAPI void eina_log_print_cb_stdout(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); +EAPI void eina_log_print_cb_stderr(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); EAPI void eina_log_print_cb_file(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); /** Modified: trunk/eina/src/lib/eina_log.c =================================================================== --- trunk/eina/src/lib/eina_log.c 2009-09-02 23:11:22 UTC (rev 42195) +++ trunk/eina/src/lib/eina_log.c 2009-09-02 23:28:00 UTC (rev 42196) @@ -338,6 +338,7 @@ // Disable color flag (can be changed through the env var // EINA_LOG_ENV_COLOR_DISABLE). static Eina_Bool _disable_color = EINA_FALSE; +static Eina_Bool _abort_on_critical = EINA_FALSE; // List of domains registered static Eina_Log_Domain *_log_domains = NULL; @@ -345,7 +346,7 @@ static int _log_domains_allocated = 0; // Default function for printing on domains -static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stdout; +static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stderr; static void *_print_cb_data = NULL; #ifdef DEBUG @@ -593,6 +594,14 @@ * eina_log_shutdown() must be called to shut down the log * module. * + * The default logging method is eina_log_print_cb_stderr(), which + * will output fancy colored messages to standard error stream. See + * its documentation on how to disable coloring. + * + * This module will optionally abort program execution if message + * level is below or equal to @c EINA_LOG_LEVEL_CRITICAL and + * @c EINA_LOG_ABORT=1. + * * @see eina_init() */ EAPI int @@ -607,6 +616,9 @@ if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)) && (atoi(tmp) == 1)) _disable_color = EINA_TRUE; + if ((tmp = getenv(EINA_LOG_ENV_ABORT)) && (atoi(tmp) == 1)) + _abort_on_critical = EINA_TRUE; + // Global log level if ((level = getenv(EINA_LOG_ENV_LEVEL))) _log_level = atoi(level); @@ -670,6 +682,11 @@ return --_eina_log_init_count; } +/** + * Sets logging method to use. + * + * By default, eina_log_print_cb_stderr() is used. + */ EAPI void eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data) { @@ -768,7 +785,41 @@ d->deleted = 1; } +/** + * Default logging method, this will output to standard error stream. + * + * This method will colorize output based on domain provided color and + * message logging level. To disable color, set environment variable + * EINA_LOG_COLOR_DISABLE=1 + */ EAPI void +eina_log_print_cb_stderr(const Eina_Log_Domain *d, Eina_Log_Level level, + const char *file, const char *fnc, int line, const char *fmt, + __UNUSED__ void *data, va_list args) +{ + EINA_SAFETY_ON_NULL_RETURN(d); + + // Normalize levels for printing. Negative leveled messages go will have + // same color as CRITICAL and higher than debug will be regular blue. + if (level < 0) level = 0; + else if (level > 4) level = 5; + + fprintf(stderr, + "%s %s%s:%d %s()%s ", d->domain_str, + (!_disable_color) ? _colors[level] : "", + file, line, fnc, + (!_disable_color) ? EINA_COLOR_RESET: ""); + vprintf(fmt, args); +} + +/** + * Alternative logging method, this will output to standard output stream. + * + * This method will colorize output based on domain provided color and + * message logging level. To disable color, set environment variable + * EINA_LOG_COLOR_DISABLE=1 + */ +EAPI void eina_log_print_cb_stdout(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, __UNUSED__ void *data, va_list args) @@ -787,6 +838,11 @@ vprintf(fmt, args); } +/** + * Alternative logging method, this will output to given file stream. + * + * This method will never output color. + */ EAPI void eina_log_print_cb_file(const Eina_Log_Domain *d, __UNUSED__ Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, @@ -814,8 +870,8 @@ EINA_SAFETY_ON_NULL_RETURN(fnc); EINA_SAFETY_ON_NULL_RETURN(fmt); - if (domain >= _log_domains_count) return; - if (domain < 0) return; + if (EINA_UNLIKELY(domain >= _log_domains_count)) return; + if (EINA_UNLIKELY(domain < 0)) return; d = &_log_domains[domain]; @@ -825,6 +881,7 @@ _print_cb(d, level, file, fnc, line, fmt, _print_cb_data, args); va_end(args); - if ((getenv(EINA_LOG_ENV_ABORT) && level <= EINA_LOG_LEVEL_CRITICAL)) + if (EINA_UNLIKELY(_abort_on_critical) && + EINA_UNLIKELY(level <= EINA_LOG_LEVEL_CRITICAL)) abort(); } |
From: Enlightenment S. <no-...@en...> - 2009-09-03 00:07:37
|
Log: eina_log: fix stderr, improve log output. * stderr logger was doing prefix properly but user message to stdout, fixed. * log is improved: * grep-able, it shows the 3 letter level name as prefix, unknown levels will have their number printed. * colors just on prefix, less polluted output still easy to spot. * function names are highlighted. Author: barbieri Date: 2009-09-02 17:07:25 -0700 (Wed, 02 Sep 2009) New Revision: 42197 Modified: trunk/eina/src/include/eina_log.h trunk/eina/src/lib/eina_log.c Modified: trunk/eina/src/include/eina_log.h =================================================================== --- trunk/eina/src/include/eina_log.h 2009-09-02 23:28:00 UTC (rev 42196) +++ trunk/eina/src/include/eina_log.h 2009-09-03 00:07:25 UTC (rev 42197) @@ -31,6 +31,7 @@ #define EINA_COLOR_WHITE "\033[37;1m" #define EINA_COLOR_LIGHTBLUE "\033[36;1m" #define EINA_COLOR_RESET "\033[0m" +#define EINA_COLOR_HIGH "\033[1m" /** * @addtogroup Eina_Tools_Group Tools Modified: trunk/eina/src/lib/eina_log.c =================================================================== --- trunk/eina/src/lib/eina_log.c 2009-09-02 23:28:00 UTC (rev 42196) +++ trunk/eina/src/lib/eina_log.c 2009-09-03 00:07:25 UTC (rev 42197) @@ -295,6 +295,8 @@ #include "eina_log.h" #include "eina_inlist.h" +#include <assert.h> + /* TODO * + printing logs to stdout or stderr can be implemented * using a queue, useful for multiple threads printing @@ -358,7 +360,7 @@ #endif // Default colors and levels -static const char *_colors[EINA_LOG_LEVELS + 1] = { // + 1 for higher than debug +static const char *_colors[] = { // + 1 for higher than debug EINA_COLOR_LIGHTRED, // EINA_LOG_LEVEL_CRITICAL EINA_COLOR_RED, // EINA_LOG_LEVEL_ERR EINA_COLOR_YELLOW, // EINA_LOG_LEVEL_WARN @@ -367,6 +369,14 @@ EINA_COLOR_BLUE, // Higher than DEBUG }; +static const char *_names[] = { + "CRI", + "ERR", + "WRN", + "INF", + "DBG", +}; + /* * Creates a colored domain name string. */ @@ -612,6 +622,9 @@ if (_eina_log_init_count) return ++_eina_log_init_count; + assert((sizeof(_names)/sizeof(_names[0])) == EINA_LOG_LEVELS); + assert((sizeof(_colors)/sizeof(_colors[0])) == EINA_LOG_LEVELS + 1); + // Check if color is disabled if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)) && (atoi(tmp) == 1)) _disable_color = EINA_TRUE; @@ -797,19 +810,37 @@ const char *file, const char *fnc, int line, const char *fmt, __UNUSED__ void *data, va_list args) { - EINA_SAFETY_ON_NULL_RETURN(d); + const char *color, *name; + char buf[4]; - // Normalize levels for printing. Negative leveled messages go will have - // same color as CRITICAL and higher than debug will be regular blue. - if (level < 0) level = 0; - else if (level > 4) level = 5; + if (EINA_UNLIKELY(level < 0)) + { + color = _colors[0]; + snprintf(buf, sizeof(buf), "%03d", level); + name = buf; + } + else if (EINA_UNLIKELY(level > EINA_LOG_LEVELS)) + { + color = _colors[EINA_LOG_LEVELS]; + snprintf(buf, sizeof(buf), "%03d", level); + name = buf; + } + else + { + color = _colors[level]; + name = _names[level]; + } - fprintf(stderr, - "%s %s%s:%d %s()%s ", d->domain_str, - (!_disable_color) ? _colors[level] : "", - file, line, fnc, - (!_disable_color) ? EINA_COLOR_RESET: ""); - vprintf(fmt, args); + if (EINA_UNLIKELY(_disable_color)) + fprintf(stderr, + "%s:%s %s:%d %s() ", + name, d->domain_str, file, line, fnc); + else + fprintf(stderr, + "%s%s" EINA_COLOR_RESET ":%s %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, d->domain_str, file, line, fnc); + vfprintf(stderr, fmt, args); } /** @@ -824,17 +855,34 @@ const char *file, const char *fnc, int line, const char *fmt, __UNUSED__ void *data, va_list args) { - EINA_SAFETY_ON_NULL_RETURN(d); + const char *color, *name; + char buf[4]; - // Normalize levels for printing. Negative leveled messages go will have - // same color as CRITICAL and higher than debug will be regular blue. - if (level < 0) level = 0; - else if (level > 4) level = 5; + if (EINA_UNLIKELY(level < 0)) + { + color = _colors[0]; + snprintf(buf, sizeof(buf), "%03d", level); + name = buf; + } + else if (EINA_UNLIKELY(level > EINA_LOG_LEVELS)) + { + color = _colors[EINA_LOG_LEVELS]; + snprintf(buf, sizeof(buf), "%03d", level); + name = buf; + } + else + { + color = _colors[level]; + name = _names[level]; + } - printf("%s %s%s:%d %s()%s ", d->domain_str, - (!_disable_color) ? _colors[level] : "", - file, line, fnc, - (!_disable_color) ? EINA_COLOR_RESET: ""); + if (EINA_UNLIKELY(_disable_color)) + printf("%s:%s %s:%d %s() ", + name, d->domain_str, file, line, fnc); + else + printf("%s%s" EINA_COLOR_RESET ":%s %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, d->domain_str, file, line, fnc); vprintf(fmt, args); } |
From: Enlightenment S. <no-...@en...> - 2009-09-03 02:28:17
|
Log: eina_log: thread safe logging! eina_log_threads_enable() and then get thread safe logging with non-main threads being printed with special notation to easily spot those. Author: barbieri Date: 2009-09-02 18:31:26 -0700 (Wed, 02 Sep 2009) New Revision: 42199 Modified: trunk/eina/src/include/eina_log.h trunk/eina/src/lib/eina_log.c Modified: trunk/eina/src/include/eina_log.h =================================================================== --- trunk/eina/src/include/eina_log.h 2009-09-03 00:17:27 UTC (rev 42198) +++ trunk/eina/src/include/eina_log.h 2009-09-03 01:31:26 UTC (rev 42199) @@ -28,6 +28,7 @@ #define EINA_COLOR_BLUE "\033[34;1m" #define EINA_COLOR_GREEN "\033[32;1m" #define EINA_COLOR_YELLOW "\033[33;1m" +#define EINA_COLOR_ORANGE "\033[0;33m" #define EINA_COLOR_WHITE "\033[37;1m" #define EINA_COLOR_LIGHTBLUE "\033[36;1m" #define EINA_COLOR_RESET "\033[0m" @@ -177,6 +178,7 @@ EAPI int eina_log_init(void); EAPI int eina_log_shutdown(void); +EAPI void eina_log_threads_enable(void); /* * Customization Modified: trunk/eina/src/lib/eina_log.c =================================================================== --- trunk/eina/src/lib/eina_log.c 2009-09-03 00:17:27 UTC (rev 42198) +++ trunk/eina/src/lib/eina_log.c 2009-09-03 01:31:26 UTC (rev 42199) @@ -342,6 +342,48 @@ static Eina_Bool _disable_color = EINA_FALSE; static Eina_Bool _abort_on_critical = EINA_FALSE; +#ifdef EFL_HAVE_PTHREAD +#include <pthread.h> +static Eina_Bool _threads_enabled = EINA_FALSE; +static pthread_t _main_thread; +static pthread_spinlock_t _log_lock; +#define LOCK() \ + do { \ + if (0) \ + fprintf(stderr, "+++LOG LOCKED! [%s, %lu]\n", \ + __FUNCTION__, pthread_self()); \ + if (EINA_UNLIKELY(_threads_enabled)) \ + pthread_spin_lock(&_log_lock); \ + } while (0) +#define UNLOCK() \ + do { \ + if (EINA_UNLIKELY(_threads_enabled)) \ + pthread_spin_unlock(&_log_lock); \ + if (0) \ + fprintf(stderr, \ + "---LOG UNLOCKED! [%s, %lu]\n", \ + __FUNCTION__, pthread_self()); \ + } while (0) +#define IS_MAIN(t) pthread_equal(t, _main_thread) +#define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t)) +#define CHECK_MAIN(...) \ + do { \ + if (!IS_MAIN(pthread_self())) { \ + fprintf(stderr, \ + "ERR: not main thread! current=%lu, main=%lu\n", \ + pthread_self(), _main_thread); \ + return __VA_ARGS__; \ + } \ + } while (0) +#else +#define LOCK() do {} while (0) +#define UNLOCK() do {} while (0) +#define IS_MAIN(t) (1) +#define IS_OTHER(t) (0) +#define CHECK_MAIN(...) do {} while (0) +#endif + + // List of domains registered static Eina_Log_Domain *_log_domains = NULL; static int _log_domains_count = 0; @@ -613,6 +655,10 @@ * @c EINA_LOG_ABORT=1. * * @see eina_init() + * + * @warning Not-MT: just call this function from main thread! The + * place where this function was called the first time is + * considered the main thread. */ EAPI int eina_log_init(void) @@ -625,6 +671,11 @@ assert((sizeof(_names)/sizeof(_names[0])) == EINA_LOG_LEVELS); assert((sizeof(_colors)/sizeof(_colors[0])) == EINA_LOG_LEVELS + 1); +#ifdef EFL_HAVE_PTHREAD + _main_thread = pthread_self(); + pthread_spin_init(&_log_lock, PTHREAD_PROCESS_PRIVATE); +#endif + // Check if color is disabled if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)) && (atoi(tmp) == 1)) _disable_color = EINA_TRUE; @@ -666,12 +717,18 @@ * the log list. * * @see eina_shutdown() + * + * @warning Not-MT: just call this function from main thread! The + * place where eina_log_init() was called the first time is + * considered the main thread. */ EAPI int eina_log_shutdown(void) { Eina_Inlist *tmp; + CHECK_MAIN(0); + if (_eina_log_init_count != 1) return --_eina_log_init_count; while (_log_domains_count--) @@ -692,19 +749,57 @@ free(tmp); } +#ifdef EFL_HAVE_PTHREAD + pthread_spin_destroy(&_log_lock); + _threads_enabled = 0; +#endif + return --_eina_log_init_count; } /** + * Enable logging module to handle threads. + * + * There is no disable option on purpose, if it is enabled, there is + * no way back until you call the last eina_log_shutdown(). + * + * There is no function to retrieve if threads are enabled as one is + * not supposed to know this from outside. + * + * After this call is executed at least once, if Eina was compiled + * with threads support then logging will lock around debug messages + * and threads that are not the main thread will have its identifier + * printed. + * + * The main thread is considered the thread where the first + * eina_log_init() was called. + */ +EAPI void +eina_log_threads_enable(void) +{ +#ifdef EFL_HAVE_PTHREAD + _threads_enabled = 1; +#endif +} + +/** * Sets logging method to use. * * By default, eina_log_print_cb_stderr() is used. + * + * @note MT: safe to call from any thread. + * + * @note MT: given function @a cb will be called protected by mutex. + * This means you're safe from other calls but you should never + * call eina_log_print(), directly or indirectly. */ EAPI void eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data) { + LOCK(); _print_cb = cb; _print_cb_data = data; + UNLOCK(); } /** @@ -715,26 +810,18 @@ * This function sets the log log level @p level. It is used in * eina_log_print(). */ -EAPI void eina_log_level_set(Eina_Log_Level level) +EAPI void +eina_log_level_set(Eina_Log_Level level) { - _log_level = level; + _log_level = level; } -/* - * @param name Domain name - * @param color Color of the domain name - * - * @return Domain index that will be used as the DOMAIN parameter on log - * macros. A negative return value means an log ocurred. - */ -EAPI int -eina_log_domain_register(const char *name, const char *color) +static inline int +eina_log_domain_register_unlocked(const char *name, const char *color) { Eina_Log_Domain_Level_Pending *pending = NULL; int i; - EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); - for (i = 0; i < _log_domains_count; i++) { if (_log_domains[i].deleted) @@ -786,9 +873,32 @@ return i; } -EAPI void -eina_log_domain_unregister(int domain) +/** + * @param name Domain name + * @param color Color of the domain name + * + * @return Domain index that will be used as the DOMAIN parameter on log + * macros. A negative return value means an log ocurred. + * + * @note MT: safe to call from any thread. + */ +EAPI int +eina_log_domain_register(const char *name, const char *color) { + int r; + + EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); + + LOCK(); + r = eina_log_domain_register_unlocked(name, color); + UNLOCK(); + return r; +} + + +static inline void +eina_log_domain_unregister_unlocked(int domain) +{ Eina_Log_Domain *d; if (domain >= _log_domains_count) return; @@ -799,11 +909,32 @@ } /** + * Forget about a logging domain registered by eina_log_domain_register() + * + * @param domain domain identifier as reported by eina_log_domain_register(), + * must be >= 0. + * + * @note MT: safe to call from any thread. + */ +EAPI void +eina_log_domain_unregister(int domain) +{ + EINA_SAFETY_ON_FALSE_RETURN(domain >= 0); + LOCK(); + eina_log_domain_unregister_unlocked(domain); + UNLOCK(); +} + +/** * Default logging method, this will output to standard error stream. * * This method will colorize output based on domain provided color and * message logging level. To disable color, set environment variable * EINA_LOG_COLOR_DISABLE=1 + * + * @note MT: if threads are enabled, this function is called within locks. + * @note MT: Threads different from main thread will have thread id + * appended to domain name. */ EAPI void eina_log_print_cb_stderr(const Eina_Log_Domain *d, Eina_Log_Level level, @@ -832,14 +963,43 @@ } if (EINA_UNLIKELY(_disable_color)) - fprintf(stderr, - "%s:%s %s:%d %s() ", - name, d->domain_str, file, line, fnc); + { +#ifdef EFL_HAVE_PTHREAD + if (_threads_enabled) + { + pthread_t cur = pthread_self(); + if (IS_OTHER(cur)) + { + fprintf(stderr, "%s:%s[T:%lu] %s:%d %s() ", + name, d->domain_str, cur, file, line, fnc); + goto end; + } + } +#endif + fprintf(stderr, "%s:%s %s:%d %s() ", + name, d->domain_str, file, line, fnc); + } else - fprintf(stderr, - "%s%s" EINA_COLOR_RESET ":%s %s:%d " - EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", - color, name, d->domain_str, file, line, fnc); + { +#ifdef EFL_HAVE_PTHREAD + if (_threads_enabled) + { + pthread_t cur = pthread_self(); + if (IS_OTHER(cur)) + { + fprintf(stderr, "%s%s" EINA_COLOR_RESET ":%s[T:" + EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, d->domain_str, cur, file, line, fnc); + goto end; + } + } +#endif + fprintf(stderr, "%s%s" EINA_COLOR_RESET ":%s %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, d->domain_str, file, line, fnc); + } + end: vfprintf(stderr, fmt, args); } @@ -849,6 +1009,10 @@ * This method will colorize output based on domain provided color and * message logging level. To disable color, set environment variable * EINA_LOG_COLOR_DISABLE=1 + * + * @note MT: if threads are enabled, this function is called within locks. + * @note MT: Threads different from main thread will have thread id + * appended to domain name. */ EAPI void eina_log_print_cb_stdout(const Eina_Log_Domain *d, Eina_Log_Level level, @@ -877,12 +1041,43 @@ } if (EINA_UNLIKELY(_disable_color)) - printf("%s:%s %s:%d %s() ", - name, d->domain_str, file, line, fnc); + { +#ifdef EFL_HAVE_PTHREAD + if (_threads_enabled) + { + pthread_t cur = pthread_self(); + if (IS_OTHER(cur)) + { + printf("%s:%s[T:%lu] %s:%d %s() ", + name, d->domain_str, cur, file, line, fnc); + goto end; + } + } +#endif + printf("%s:%s %s:%d %s() ", + name, d->domain_str, file, line, fnc); + } else - printf("%s%s" EINA_COLOR_RESET ":%s %s:%d " - EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", - color, name, d->domain_str, file, line, fnc); + { +#ifdef EFL_HAVE_PTHREAD + if (_threads_enabled) + { + pthread_t cur = pthread_self(); + if (IS_OTHER(cur)) + { + printf("%s%s" EINA_COLOR_RESET ":%s[T:" + EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, d->domain_str, cur, file, line, fnc); + goto end; + } + } +#endif + printf("%s%s" EINA_COLOR_RESET ":%s %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, d->domain_str, file, line, fnc); + } + end: vprintf(fmt, args); } @@ -890,6 +1085,10 @@ * Alternative logging method, this will output to given file stream. * * This method will never output color. + * + * @note MT: if threads are enabled, this function is called within locks. + * @note MT: Threads different from main thread will have thread id + * appended to domain name. */ EAPI void eina_log_print_cb_file(const Eina_Log_Domain *d, __UNUSED__ Eina_Log_Level level, @@ -897,33 +1096,28 @@ void *data, va_list args) { FILE *f = data; +#ifdef EFL_HAVE_PTHREAD + if (_threads_enabled) + { + pthread_t cur = pthread_self(); + if (IS_OTHER(cur)) + { + fprintf(f, "%s[T:%lu] %s:%d %s() ", d->name, cur, file, line, fnc); + goto end; + } + } +#endif fprintf(f, "%s %s:%d %s() ", d->name, file, line, fnc); + end: vfprintf(f, fmt, args); } -EAPI void -eina_log_print(int domain, Eina_Log_Level level, const char *file, - const char *fnc, int line, const char *fmt, ...) +static inline void +eina_log_print_unlocked(int domain, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, va_list args) { Eina_Log_Domain *d; - va_list args; #ifdef EINA_SAFETY_CHECKS - if (EINA_UNLIKELY(file == NULL)) - { - fputs("ERR: eina_log_print() file == NULL\n", stderr); - return; - } - if (EINA_UNLIKELY(fnc == NULL)) - { - fputs("ERR: eina_log_print() fnc == NULL\n", stderr); - return; - } - if (EINA_UNLIKELY(fmt == NULL)) - { - fputs("ERR: eina_log_print() fmt == NULL\n", stderr); - return; - } if (EINA_UNLIKELY(domain >= _log_domains_count) || EINA_UNLIKELY(domain < 0)) { @@ -942,11 +1136,60 @@ if (level > d->level) return; - va_start(args, fmt); _print_cb(d, level, file, fnc, line, fmt, _print_cb_data, args); - va_end(args); if (EINA_UNLIKELY(_abort_on_critical) && EINA_UNLIKELY(level <= EINA_LOG_LEVEL_CRITICAL)) abort(); } + +/** + * Print out log message using given domain and level. + * + * @note Usually you'll not use this function directly but the helper + * macros EINA_LOG(), EINA_LOG_DOM_CRIT(), EINA_LOG_CRIT() and + * so on. See eina_log.h + * + * @param domain logging domain to use or @c EINA_LOG_DOMAIN_GLOBAL if + * you registered none. It is recommended that modules and + * applications have their own logging domain. + * @param level message level, those with level greater than user + * specified value (eina_log_level_set() or environment + * variables EINA_LOG_LEVEL, EINA_LOG_LEVELS) will be ignored. + * @param file filename that originated the call, must @b not be @c NULL. + * @param fnc function that originated the call, must @b not be @c NULL. + * @param line originating line in @a file. + * @param fmt printf-like format to use. + * + * @note MT: this function may be called from different threads if + * eina_log_threads_enable() was called before. + */ +EAPI void +eina_log_print(int domain, Eina_Log_Level level, const char *file, + const char *fnc, int line, const char *fmt, ...) +{ + va_list args; + +#ifdef EINA_SAFETY_CHECKS + if (EINA_UNLIKELY(file == NULL)) + { + fputs("ERR: eina_log_print() file == NULL\n", stderr); + return; + } + if (EINA_UNLIKELY(fnc == NULL)) + { + fputs("ERR: eina_log_print() fnc == NULL\n", stderr); + return; + } + if (EINA_UNLIKELY(fmt == NULL)) + { + fputs("ERR: eina_log_print() fmt == NULL\n", stderr); + return; + } +#endif + va_start(args, fmt); + LOCK(); + eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); + UNLOCK(); + va_end(args); +} |
From: Enlightenment S. <no-...@en...> - 2009-09-04 00:53:32
|
Log: eina_safety_checks_init() All these individual init functions are getting messy, some modules lack them and it's easy to get inconsistent. Safety check needs error and log, but these need safety checks as well, some modules (lalloc, rbtree and others) use safety checks but provide no _init(). I want to know if we really gain something to init individual modules. It should not be that expensive as init should not allocate heavy resources and the recommendation is to call eina_init() so most users will do that anyway. If people agree I'll unmark all *_init() as EAPI and make them private to eina lib. Author: barbieri Date: 2009-09-03 17:53:19 -0700 (Thu, 03 Sep 2009) New Revision: 42214 Modified: trunk/eina/src/include/eina_safety_checks.h trunk/eina/src/lib/Makefile.am trunk/eina/src/lib/eina_array.c trunk/eina/src/lib/eina_convert.c trunk/eina/src/lib/eina_counter.c trunk/eina/src/lib/eina_error.c trunk/eina/src/lib/eina_hash.c trunk/eina/src/lib/eina_list.c trunk/eina/src/lib/eina_log.c trunk/eina/src/lib/eina_main.c trunk/eina/src/lib/eina_mempool.c trunk/eina/src/lib/eina_module.c trunk/eina/src/lib/eina_rectangle.c trunk/eina/src/lib/eina_stringshare.c Modified: trunk/eina/src/include/eina_safety_checks.h =================================================================== --- trunk/eina/src/include/eina_safety_checks.h 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/include/eina_safety_checks.h 2009-09-04 00:53:19 UTC (rev 42214) @@ -19,9 +19,64 @@ #ifndef EINA_SAFETY_CHECKS_H_ #define EINA_SAFETY_CHECKS_H_ +/** + * @addtogroup Eina_Tools_Group Tools + * + * @{ + */ +/** + * @defgroup Eina_Safety_Checks_Group Safety Checks + * + * @warning @c eina_safety_checks.h should only be included by source + * files, after all other includes and before the source file + * specific includes. By source file specific includes we + * mean those that define the functions that are being + * checked. The reason for such complexity is the trick to + * avoid compiler optimizations. If compilers are told that + * some given function will never receive @c NULL + * (EINA_ARG_NONNULL(), then compiler will emit a warning if + * it detects so (good!) but will remove any checks for that + * condition as it believes it will never happen, removing + * all safety checks! By including @c eina_safety_checks.h it + * will redefine EINA_ARG_NONNULL() to void and compiler + * warning will not be emitted, but checks will be there. The + * files already processed with the old macro + * EINA_ARG_NONNULL() will still work and emit the warnings. + * + * + * @code + * + * // all these files will emit warning from EINA_ARG_NONNULL() + * #include <Evas.h> // third party headers + * #include <Ecore.h> + * #include <eina_error.h> // eina own header + * + * #include <eina_safety_checks.h> + * // all these files below will NOT emit warning from EINA_ARG_NONNULL(), + * // but this is required to have the functions defined there to be checked + * // for NULL pointers + * #include "my_functions1.h" + * #include "my_functions2.h" + * + * @endcode + * + * @{ + */ + + #include "eina_config.h" +#include "eina_error.h" +EAPI int eina_safety_checks_init(void); +EAPI int eina_safety_checks_shutdown(void); + +/** + * @var EINA_ERROR_SAFETY_FAILED + * Error identifier corresponding to safety check failure. + */ +EAPI extern Eina_Error EINA_ERROR_SAFETY_FAILED; + #ifdef EINA_SAFETY_CHECKS #include "eina_log.h" @@ -31,6 +86,7 @@ { \ if (EINA_UNLIKELY((exp) == NULL)) \ { \ + eina_error_set(EINA_ERROR_SAFETY_FAILED); \ EINA_LOG_ERR("%s", "safety check failed: " #exp " == NULL"); \ return; \ } \ @@ -42,6 +98,7 @@ { \ if (EINA_UNLIKELY((exp) == NULL)) \ { \ + eina_error_set(EINA_ERROR_SAFETY_FAILED); \ EINA_LOG_ERR("%s", "safety check failed: " #exp " == NULL"); \ return (val); \ } \ @@ -53,6 +110,7 @@ { \ if (EINA_UNLIKELY(exp)) \ { \ + eina_error_set(EINA_ERROR_SAFETY_FAILED); \ EINA_LOG_ERR("%s", "safety check failed: " #exp " is true"); \ return; \ } \ @@ -64,6 +122,7 @@ { \ if (EINA_UNLIKELY(exp)) \ { \ + eina_error_set(EINA_ERROR_SAFETY_FAILED); \ EINA_LOG_ERR("%s", "safety check failed: " #exp " is true"); \ return val; \ } \ @@ -75,6 +134,7 @@ { \ if (EINA_UNLIKELY(!(exp))) \ { \ + eina_error_set(EINA_ERROR_SAFETY_FAILED); \ EINA_LOG_ERR("%s", "safety check failed: " #exp " is false"); \ return; \ } \ @@ -86,6 +146,7 @@ { \ if (EINA_UNLIKELY(!(exp))) \ { \ + eina_error_set(EINA_ERROR_SAFETY_FAILED); \ EINA_LOG_ERR("%s", "safety check failed: " #exp " is false"); \ return val; \ } \ @@ -121,3 +182,7 @@ #endif /* safety checks macros */ #endif /* EINA_SAFETY_CHECKS_H_ */ + +/** + * @} + */ Modified: trunk/eina/src/lib/Makefile.am =================================================================== --- trunk/eina/src/lib/Makefile.am 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/Makefile.am 2009-09-04 00:53:19 UTC (rev 42214) @@ -34,7 +34,8 @@ eina_stringshare.c \ eina_cpu.c \ eina_tiler.c \ -eina_hamster.c +eina_hamster.c \ +eina_safety_checks.c if EINA_STATIC_BUILD_CHAINED_POOL Modified: trunk/eina/src/lib/eina_array.c =================================================================== --- trunk/eina/src/lib/eina_array.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_array.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -375,6 +375,13 @@ return 0; } + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_error_shutdown(); + return 0; + } + if (!eina_magic_string_init()) { EINA_ERROR_PERR("ERROR: Could not initialize eina magic string module.\n"); @@ -421,6 +428,7 @@ if (!_eina_array_init_count) { eina_magic_string_shutdown(); + eina_safety_checks_shutdown(); eina_error_shutdown(); } Modified: trunk/eina/src/lib/eina_convert.c =================================================================== --- trunk/eina/src/lib/eina_convert.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_convert.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -23,6 +23,7 @@ #include <math.h> #include <stdlib.h> #include <string.h> +#include <stdio.h> #include "eina_config.h" #include "eina_safety_checks.h" @@ -222,6 +223,13 @@ EINA_ERROR_CONVERT_P_NOT_FOUND = eina_error_msg_register("Error during string convertion to float, First 'p' was not found."); EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = eina_error_msg_register("Error outrun string limit during convertion string convertion to float."); + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_error_shutdown(); + return 0; + } + init_out: return _eina_convert_init_count; } @@ -243,6 +251,7 @@ if (_eina_convert_init_count > 0) goto shutdown_out; + eina_safety_checks_shutdown(); eina_error_shutdown(); shutdown_out: Modified: trunk/eina/src/lib/eina_counter.c =================================================================== --- trunk/eina/src/lib/eina_counter.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_counter.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -268,6 +268,14 @@ return 0; } #endif /* _WIN2 */ + + + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_error_shutdown(); + return 0; + } } return _eina_counter_init_count; @@ -292,7 +300,11 @@ { _eina_counter_init_count--; - if (_eina_counter_init_count == 0) eina_error_shutdown(); + if (_eina_counter_init_count == 0) + { + eina_error_shutdown(); + eina_safety_checks_shutdown(); + } return _eina_counter_init_count; } Modified: trunk/eina/src/lib/eina_error.c =================================================================== --- trunk/eina/src/lib/eina_error.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_error.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -525,18 +525,25 @@ */ EAPI int eina_error_init(void) { - if (!_eina_error_init_count) - { - char *level; - /* TODO register the eina's basic errors */ - if ((level = getenv("EINA_ERROR_LEVEL"))) - { - _error_level = atoi(level); - } - EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_register("Out of memory"); - } - /* get all the modules */ - return ++_eina_error_init_count; + const char *level; + + _eina_error_init_count++; + if (_eina_error_init_count != 1) + return _eina_error_init_count; + + /* TODO register the eina's basic errors */ + if ((level = getenv("EINA_ERROR_LEVEL"))) + _error_level = atoi(level); + + EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_register("Out of memory"); + + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + _eina_error_init_count = 0; + return 0; + } + return 1; } /** @@ -569,6 +576,7 @@ free(tmp); } _error_list_count = 0; + eina_safety_checks_shutdown(); } return _eina_error_init_count; } Modified: trunk/eina/src/lib/eina_hash.c =================================================================== --- trunk/eina/src/lib/eina_hash.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_hash.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -658,12 +658,21 @@ eina_hash_init(void) { if (!_eina_hash_init_count) - if (!eina_error_init()) - { - fprintf(stderr, "Could not initialize eina error module\n"); - return 0; - } + { + if (!eina_error_init()) + { + fprintf(stderr, "Could not initialize eina error module\n"); + return 0; + } + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_error_shutdown(); + return 0; + } + } + return ++_eina_hash_init_count; } @@ -682,7 +691,10 @@ eina_hash_shutdown(void) { if (_eina_hash_init_count == 1) - eina_error_shutdown(); + { + eina_safety_checks_shutdown(); + eina_error_shutdown(); + } return --_eina_hash_init_count; } Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_list.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -468,6 +468,13 @@ return 0; } + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_error_shutdown(); + return 0; + } + if (!eina_magic_string_init()) { EINA_ERROR_PERR("ERROR: Could not initialize eina magic string module.\n"); @@ -551,6 +558,7 @@ eina_mempool_shutdown(); eina_magic_string_shutdown(); + eina_safety_checks_shutdown(); eina_error_shutdown(); } Modified: trunk/eina/src/lib/eina_log.c =================================================================== --- trunk/eina/src/lib/eina_log.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_log.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -663,10 +663,11 @@ EAPI int eina_log_init(void) { - char *level; - char *tmp; + const char *level, *tmp; - if (_eina_log_init_count) return ++_eina_log_init_count; + _eina_log_init_count++; + if (_eina_log_init_count != 1) + return _eina_log_init_count; assert((sizeof(_names)/sizeof(_names[0])) == EINA_LOG_LEVELS); assert((sizeof(_colors)/sizeof(_colors[0])) == EINA_LOG_LEVELS + 1); @@ -695,13 +696,21 @@ if (EINA_LOG_DOMAIN_GLOBAL < 0) { fprintf(stderr, "Failed to create global logging domain.\n"); + _eina_log_init_count = 0; return 0; } // Parse pending domains passed through EINA_LOG_LEVELS eina_log_domain_parse_pendings(); - return ++_eina_log_init_count; + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_log_shutdown(); /* zero _eina_log_init_count and free stuff */ + return 0; + } + + return 1; } /** Modified: trunk/eina/src/lib/eina_main.c =================================================================== --- trunk/eina/src/lib/eina_main.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_main.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -26,6 +26,7 @@ #include "eina_types.h" #include "eina_main.h" #include "eina_error.h" +#include "eina_safety_checks.h" #include "eina_log.h" #include "eina_hash.h" #include "eina_stringshare.h" @@ -79,6 +80,8 @@ * (in that order): * * @li eina_error_init() + * @li eina_log_init() + * @li eina_safety_checks_init() * @li eina_hash_init() * @li eina_stringshare_init() * @li eina_list_init() @@ -108,6 +111,12 @@ goto log_init_error; } + if (!eina_safety_checks_init()) + { + EINA_ERROR_PERR("Could not initialize eina safety checks module.\n"); + goto safety_checks_init_error; + } + if (!eina_hash_init()) { EINA_ERROR_PERR("Could not initialize eina hash module.\n"); @@ -168,6 +177,8 @@ eina_hash_shutdown(); hash_init_error: eina_log_shutdown(); + safety_checks_init_error: + eina_safety_checks_shutdown(); log_init_error: eina_error_shutdown(); @@ -185,15 +196,17 @@ * it shut down all the Eina modules. The list of shut down functions * that are called are (in that order): * - * @li eina_rectangle_init() - * @li eina_magic_string_init() - * @li eina_benchmark_init() - * @li eina_counter_init() - * @li eina_array_init() - * @li eina_list_init() - * @li eina_stringshare_init() - * @li eina_hash_init() - * @li eina_error_init() + * @li eina_rectangle_shutdown() + * @li eina_magic_string_shutdown() + * @li eina_benchmark_shutdown() + * @li eina_counter_shutdown() + * @li eina_array_shutdown() + * @li eina_list_shutdown() + * @li eina_stringshare_shutdown() + * @li eina_hash_shutdown() + * @li eina_safety_checks_shutdown() + * @li eina_log_shutdown() + * @li eina_error_shutdown() * * Once this function succeeds (that is, @c 0 is returned), you must * not call any of the Eina function anymore. You must call @@ -212,6 +225,7 @@ eina_list_shutdown(); eina_stringshare_shutdown(); eina_hash_shutdown(); + eina_safety_checks_shutdown(); eina_log_shutdown(); eina_error_shutdown(); Modified: trunk/eina/src/lib/eina_mempool.c =================================================================== --- trunk/eina/src/lib/eina_mempool.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_mempool.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -137,10 +137,16 @@ { char *path; + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + return 0; + } + if (!eina_hash_init()) { fprintf(stderr, "Could not initialize eina hash module.\n"); - return 0; + goto hash_init_error; } if (!eina_module_init()) { @@ -196,6 +202,8 @@ eina_module_shutdown(); module_init_error: eina_hash_shutdown(); + hash_init_error: + eina_safety_checks_shutdown(); return 0; @@ -234,6 +242,7 @@ eina_hash_free(_backends); eina_hash_shutdown(); + eina_safety_checks_shutdown(); return 0; } Modified: trunk/eina/src/lib/eina_module.c =================================================================== --- trunk/eina/src/lib/eina_module.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_module.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -215,6 +215,13 @@ return 0; } + if (!eina_safety_checks_init()) + { + EINA_LOG_ERR("Could not initialize eina safety checks."); + eina_log_shutdown(); + return 0; + } + EINA_MODULE_LOG_DOM = eina_log_domain_register ("eina_module", EINA_LOG_COLOR_DEFAULT); if (EINA_MODULE_LOG_DOM < 0) @@ -265,6 +272,8 @@ * delete the list of modules here */ + eina_safety_checks_shutdown(); + eina_log_domain_unregister(EINA_MODULE_LOG_DOM); EINA_MODULE_LOG_DOM = -1; eina_log_shutdown(); Modified: trunk/eina/src/lib/eina_rectangle.c =================================================================== --- trunk/eina/src/lib/eina_rectangle.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_rectangle.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -245,6 +245,11 @@ EINA_ERROR_PERR("Could not initialize eina error module.\n"); return 0; } + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + goto safety_checks_init_error; + } if (!eina_mempool_init()) { EINA_ERROR_PERR("Could not initialize eina mempool module.\n"); @@ -286,6 +291,8 @@ list_init_error: eina_mempool_shutdown(); mempool_init_error: + eina_safety_checks_shutdown(); + safety_checks_init_error: eina_error_shutdown(); return 0; @@ -310,6 +317,7 @@ eina_mempool_del(_eina_rectangle_mp); eina_mempool_shutdown(); + eina_safety_checks_shutdown(); eina_error_shutdown(); return 0; Modified: trunk/eina/src/lib/eina_stringshare.c =================================================================== --- trunk/eina/src/lib/eina_stringshare.c 2009-09-03 23:36:27 UTC (rev 42213) +++ trunk/eina/src/lib/eina_stringshare.c 2009-09-04 00:53:19 UTC (rev 42214) @@ -829,6 +829,13 @@ return 0; } + if (!eina_safety_checks_init()) + { + fprintf(stderr, "Could not initialize eina safety checks.\n"); + eina_error_shutdown(); + return 0; + } + if (!eina_magic_string_init()) { EINA_ERROR_PERR("ERROR: Could not initialize eina magic string module.\n"); @@ -883,6 +890,7 @@ _eina_stringshare_population_shutdown(); _eina_stringshare_small_shutdown(); eina_magic_string_shutdown(); + eina_safety_checks_shutdown(); eina_error_shutdown(); } |
From: Enlightenment S. <no-...@en...> - 2009-09-04 00:57:23
|
Log: eina_log_vprint() for those that want to wrap it in other functions. Author: barbieri Date: 2009-09-03 17:57:09 -0700 (Thu, 03 Sep 2009) New Revision: 42216 Modified: trunk/eina/src/include/eina_log.h trunk/eina/src/lib/eina_log.c Modified: trunk/eina/src/include/eina_log.h =================================================================== --- trunk/eina/src/include/eina_log.h 2009-09-04 00:56:16 UTC (rev 42215) +++ trunk/eina/src/include/eina_log.h 2009-09-04 00:57:09 UTC (rev 42216) @@ -192,7 +192,16 @@ EAPI int eina_log_domain_register(const char *name, const char *color) EINA_ARG_NONNULL(1); EAPI void eina_log_domain_unregister(int domain); +/* + * Logging functions. + */ EAPI void eina_log_print(int domain, Eina_Log_Level level, const char *file, const char *function, int line, const char *fmt, ...) EINA_ARG_NONNULL(2, 3, 5); +EAPI void eina_log_vprint(int domain, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, va_list args) EINA_ARG_NONNULL(2, 3, 5); + + +/* + * Logging methods (change how logging is done). + */ EAPI void eina_log_print_cb_stdout(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); EAPI void eina_log_print_cb_stderr(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); EAPI void eina_log_print_cb_file(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args); Modified: trunk/eina/src/lib/eina_log.c =================================================================== --- trunk/eina/src/lib/eina_log.c 2009-09-04 00:56:16 UTC (rev 42215) +++ trunk/eina/src/lib/eina_log.c 2009-09-04 00:57:09 UTC (rev 42216) @@ -1206,3 +1206,53 @@ UNLOCK(); va_end(args); } + +/** + * Print out log message using given domain and level. + * + * @note Usually you'll not use this function directly but the helper + * macros EINA_LOG(), EINA_LOG_DOM_CRIT(), EINA_LOG_CRIT() and + * so on. See eina_log.h + * + * @param domain logging domain to use or @c EINA_LOG_DOMAIN_GLOBAL if + * you registered none. It is recommended that modules and + * applications have their own logging domain. + * @param level message level, those with level greater than user + * specified value (eina_log_level_set() or environment + * variables EINA_LOG_LEVEL, EINA_LOG_LEVELS) will be ignored. + * @param file filename that originated the call, must @b not be @c NULL. + * @param fnc function that originated the call, must @b not be @c NULL. + * @param line originating line in @a file. + * @param fmt printf-like format to use. Should not provide trailing + * '\n' as it is automatically included. + * + * @note MT: this function may be called from different threads if + * eina_log_threads_enable() was called before. + * + * @see eina_log_print() + */ +EAPI void +eina_log_vprint(int domain, Eina_Log_Level level, const char *file, + const char *fnc, int line, const char *fmt, va_list args) +{ +#ifdef EINA_SAFETY_CHECKS + if (EINA_UNLIKELY(file == NULL)) + { + fputs("ERR: eina_log_print() file == NULL\n", stderr); + return; + } + if (EINA_UNLIKELY(fnc == NULL)) + { + fputs("ERR: eina_log_print() fnc == NULL\n", stderr); + return; + } + if (EINA_UNLIKELY(fmt == NULL)) + { + fputs("ERR: eina_log_print() fmt == NULL\n", stderr); + return; + } +#endif + LOCK(); + eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); + UNLOCK(); +} |
From: Enlightenment S. <no-...@en...> - 2009-09-04 14:18:22
|
Log: eina_matrixsparse: loggify, install header, remove warnings and coding style. * use eina_log * install eina_matrixsparse.h * remove unused variable * fix coding style issue reported by Vincent Author: barbieri Date: 2009-09-04 07:18:05 -0700 (Fri, 04 Sep 2009) New Revision: 42246 Modified: trunk/eina/src/include/Makefile.am trunk/eina/src/lib/eina_matrixsparse.c Modified: trunk/eina/src/include/Makefile.am =================================================================== --- trunk/eina/src/include/Makefile.am 2009-09-04 14:04:23 UTC (rev 42245) +++ trunk/eina/src/include/Makefile.am 2009-09-04 14:18:05 UTC (rev 42246) @@ -37,7 +37,8 @@ eina_main.h \ eina_cpu.h \ eina_tiler.h \ -eina_hamster.h +eina_hamster.h \ +eina_matrixsparse.h installed_mainheaderdir = $(includedir)/eina-@VMAJ@ dist_installed_mainheader_DATA = Eina.h eina_config.h Modified: trunk/eina/src/lib/eina_matrixsparse.c =================================================================== --- trunk/eina/src/lib/eina_matrixsparse.c 2009-09-04 14:04:23 UTC (rev 42245) +++ trunk/eina/src/lib/eina_matrixsparse.c 2009-09-04 14:18:05 UTC (rev 42246) @@ -183,6 +183,11 @@ */ static int _eina_matrixsparse_init_count = 0; +static int _eina_matrixsparse_log_dom = -1; + +#define ERR(...) EINA_LOG_DOM_ERR(_eina_matrixsparse_log_dom, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(_eina_matrixsparse_log_dom, __VA_ARGS__) + static Eina_Mempool *_eina_matrixsparse_cell_mp = NULL; static Eina_Mempool *_eina_matrixsparse_row_mp = NULL; @@ -200,7 +205,6 @@ _eina_matrixsparse_cell_unlink(Eina_Matrixsparse_Cell *c) { Eina_Matrixsparse_Row *r = c->parent; - long *tmp = c->data; if (r->last_used == c) { @@ -681,7 +685,7 @@ return 0; if (it->dummy.col.data != NULL) - EINA_ERROR_PERR("Last iterator call changed dummy cell!\n"); + ERR("Last iterator call changed dummy cell!"); if ((it->ref.col) && (it->ref.col->col == it->idx.col) && @@ -724,7 +728,7 @@ EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it); if (it->dummy.col.data != NULL) - EINA_ERROR_PERR("Last iterator call changed dummy cell!\n"); + ERR("Last iterator call changed dummy cell!"); EINA_MAGIC_SET(it, EINA_MAGIC_NONE); EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE); @@ -785,21 +789,35 @@ if (!_eina_matrixsparse_init_count) { - if (!eina_error_init()) + if (!eina_log_init()) { - fprintf(stderr, "Could not initialize eina error module\n"); + fprintf(stderr, "Could not initialize eina logging system."); return 0; } + _eina_matrixsparse_log_dom = eina_log_domain_register("eina_matrixsparse", EINA_LOG_COLOR_DEFAULT); + if (_eina_matrixsparse_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_matrixsparse"); + eina_log_shutdown(); + return 0; + } + + if (!eina_error_init()) + { + ERR("Could not initialize eina error module."); + goto on_eina_error_fail; + } + if (!eina_magic_string_init()) { - EINA_ERROR_PERR("ERROR: Could not initialize eina magic string module.\n"); + ERR("Could not initialize eina magic string module."); goto on_magic_string_fail; } if (!eina_mempool_init()) { - EINA_ERROR_PERR("ERROR: Could not initialize eina mempool module.\n"); + ERR("Could not initialize eina mempool module."); goto on_mempool_fail; } @@ -814,7 +832,7 @@ (choice, "matrixsparse_cell", NULL, sizeof (Eina_Matrixsparse_Cell), 120); if (!_eina_matrixsparse_cell_mp) { - EINA_ERROR_PERR("ERROR: Mempool for matrixsparse_cell cannot be allocated in matrixsparse init.\n"); + ERR("Mempool for matrixsparse_cell cannot be allocated in matrixsparse init."); goto on_init_fail; } @@ -822,7 +840,7 @@ (choice, "matrixsparse_row", NULL, sizeof (Eina_Matrixsparse_Row), 120); if (!_eina_matrixsparse_row_mp) { - EINA_ERROR_PERR("ERROR: Mempool for matrixsparse_row cannot be allocated in matrixsparse init.\n"); + ERR("Mempool for matrixsparse_row cannot be allocated in matrixsparse init."); goto on_init_fail; } @@ -855,6 +873,10 @@ eina_magic_string_shutdown(); on_magic_string_fail: eina_error_shutdown(); + on_eina_error_fail: + eina_log_domain_unregister(_eina_matrixsparse_log_dom); + _eina_matrixsparse_log_dom = -1; + eina_log_shutdown(); return 0; } @@ -882,6 +904,10 @@ eina_mempool_shutdown(); eina_magic_string_shutdown(); eina_error_shutdown(); + + eina_log_domain_unregister(_eina_matrixsparse_log_dom); + _eina_matrixsparse_log_dom = -1; + eina_log_shutdown(); } return _eina_matrixsparse_init_count; @@ -1048,9 +1074,9 @@ } if (!c) { + Eina_Matrixsparse_Row *r_aux = r; r->cols = NULL; r->last_col = NULL; - Eina_Matrixsparse_Row *r_aux = r; if (r->next) r->next->prev = r->prev; else |
From: Enlightenment S. <no-...@en...> - 2009-09-07 02:34:06
|
Log: 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. Author: barbieri Date: 2009-09-06 19:33:54 -0700 (Sun, 06 Sep 2009) New Revision: 42310 Modified: trunk/eina/src/include/eina_magic.h trunk/eina/src/lib/eina_accessor.c trunk/eina/src/lib/eina_array.c trunk/eina/src/lib/eina_iterator.c trunk/eina/src/lib/eina_list.c trunk/eina/src/lib/eina_magic.c trunk/eina/src/lib/eina_main.c Modified: trunk/eina/src/include/eina_magic.h =================================================================== --- trunk/eina/src/include/eina_magic.h 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/include/eina_magic.h 2009-09-07 02:33:54 UTC (rev 42310) @@ -42,7 +42,7 @@ * 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 Modified: trunk/eina/src/lib/eina_accessor.c =================================================================== --- trunk/eina/src/lib/eina_accessor.c 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/lib/eina_accessor.c 2009-09-07 02:33:54 UTC (rev 42310) @@ -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. Modified: trunk/eina/src/lib/eina_array.c =================================================================== --- trunk/eina/src/lib/eina_array.c 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/lib/eina_array.c 2009-09-07 02:33:54 UTC (rev 42310) @@ -338,8 +338,6 @@ 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"); Modified: trunk/eina/src/lib/eina_iterator.c =================================================================== --- trunk/eina/src/lib/eina_iterator.c 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/lib/eina_iterator.c 2009-09-07 02:33:54 UTC (rev 42310) @@ -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. Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/lib/eina_list.c 2009-09-07 02:33:54 UTC (rev 42310) @@ -487,8 +487,6 @@ 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"); Modified: trunk/eina/src/lib/eina_magic.c =================================================================== --- trunk/eina/src/lib/eina_magic.c 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/lib/eina_magic.c 2009-09-07 02:33:54 UTC (rev 42310) @@ -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,14 +47,35 @@ typedef struct _Eina_Magic_String Eina_Magic_String; struct _Eina_Magic_String { - EINA_INLIST; - + Eina_Magic magic; char *string; - Eina_Magic magic; }; -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 @@ 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,16 +135,19 @@ 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 *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 @@ * @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 ; - } + EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE); - ems = malloc(sizeof (Eina_Magic_String)); - if (!ems) - return; + 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 Modified: trunk/eina/src/lib/eina_main.c =================================================================== --- trunk/eina/src/lib/eina_main.c 2009-09-07 01:23:12 UTC (rev 42309) +++ trunk/eina/src/lib/eina_main.c 2009-09-07 02:33:54 UTC (rev 42310) @@ -61,6 +61,8 @@ S(error); S(safety_checks); S(magic_string); +S(iterator); +S(accessor); S(array); S(module); S(mempool); @@ -86,6 +88,8 @@ S(error), S(safety_checks), S(magic_string), + S(iterator), + S(accessor), S(array), S(module), S(mempool), |
From: Enlightenment S. <no-...@en...> - 2009-09-07 03:32:33
|
Log: malloc--: error and magic can take statically defined strings so no need to strdup them. Author: barbieri Date: 2009-09-06 20:32:22 -0700 (Sun, 06 Sep 2009) New Revision: 42311 Modified: trunk/eina/src/include/eina_error.h trunk/eina/src/include/eina_magic.h trunk/eina/src/lib/eina_accessor.c trunk/eina/src/lib/eina_array.c trunk/eina/src/lib/eina_convert.c trunk/eina/src/lib/eina_counter.c trunk/eina/src/lib/eina_error.c trunk/eina/src/lib/eina_iterator.c trunk/eina/src/lib/eina_list.c trunk/eina/src/lib/eina_magic.c trunk/eina/src/lib/eina_matrixsparse.c trunk/eina/src/lib/eina_mempool.c trunk/eina/src/lib/eina_module.c trunk/eina/src/lib/eina_safety_checks.c trunk/eina/src/lib/eina_stringshare.c Modified: trunk/eina/src/include/eina_error.h =================================================================== --- trunk/eina/src/include/eina_error.h 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/include/eina_error.h 2009-09-07 03:32:22 UTC (rev 42311) @@ -89,7 +89,9 @@ */ EAPI extern Eina_Error EINA_ERROR_OUT_OF_MEMORY; -EAPI Eina_Error eina_error_msg_register(const char *msg) EINA_ARG_NONNULL(1); +EAPI Eina_Error eina_error_msg_register(const char *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; +EAPI Eina_Error eina_error_msg_static_register(const char *msg) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; + EAPI Eina_Error eina_error_get(void); EAPI void eina_error_set(Eina_Error err); EAPI const char * eina_error_msg_get(Eina_Error error) EINA_PURE; Modified: trunk/eina/src/include/eina_magic.h =================================================================== --- trunk/eina/src/include/eina_magic.h 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/include/eina_magic.h 2009-09-07 03:32:22 UTC (rev 42311) @@ -43,6 +43,7 @@ */ EAPI const char* eina_magic_string_get(Eina_Magic magic) EINA_PURE EINA_WARN_UNUSED_RESULT; EAPI Eina_Bool eina_magic_string_set(Eina_Magic magic, const char *magic_name) EINA_ARG_NONNULL(2); +EAPI Eina_Bool eina_magic_string_static_set(Eina_Magic magic, const char *magic_name) EINA_ARG_NONNULL(2); /** * @def EINA_MAGIC_NONE Modified: trunk/eina/src/lib/eina_accessor.c =================================================================== --- trunk/eina/src/lib/eina_accessor.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_accessor.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -40,6 +40,8 @@ * @cond LOCAL */ +static const char EINA_MAGIC_ACCESSOR_STR[] = "Eina Accessor"; + #define EINA_MAGIC_CHECK_ACCESSOR(d) \ do { \ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ACCESSOR)) \ @@ -92,7 +94,7 @@ Eina_Bool eina_accessor_init(void) { - return eina_magic_string_set(EINA_MAGIC_ACCESSOR, "Eina Accessor"); + return eina_magic_string_set(EINA_MAGIC_ACCESSOR, EINA_MAGIC_ACCESSOR_STR); } /** Modified: trunk/eina/src/lib/eina_array.c =================================================================== --- trunk/eina/src/lib/eina_array.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_array.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -134,6 +134,10 @@ * @cond LOCAL */ +static const char EINA_MAGIC_ARRAY_STR[] = "Eina Array"; +static const char EINA_MAGIC_ARRAY_ITERATOR_STR[] = "Eina Array Iterator"; +static const char EINA_MAGIC_ARRAY_ACCESSOR_STR[] = "Eina Array Accessor"; + #define EINA_MAGIC_CHECK_ARRAY(d) \ do { \ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY)) \ @@ -338,9 +342,11 @@ return EINA_FALSE; } - 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"); +#define EMS(n) eina_magic_string_static_set(n, n##_STR) + EMS(EINA_MAGIC_ARRAY); + EMS(EINA_MAGIC_ARRAY_ITERATOR); + EMS(EINA_MAGIC_ARRAY_ACCESSOR); +#undef EMS return EINA_TRUE; } Modified: trunk/eina/src/lib/eina_convert.c =================================================================== --- trunk/eina/src/lib/eina_convert.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_convert.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -84,6 +84,10 @@ EAPI Eina_Error EINA_ERROR_CONVERT_0X_NOT_FOUND = 0; EAPI Eina_Error EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = 0; +static const char EINA_ERROR_CONVERT_0X_NOT_FOUND_STR[] = "Error during string convertion to float, First '0x' was not found."; +static const char EINA_ERROR_CONVERT_P_NOT_FOUND_STR[] = "Error during string convertion to float, First 'p' was not found."; +static const char EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH_STR[] = "Error outrun string limit during convertion string convertion to float."; + /** * @endcond */ @@ -232,9 +236,11 @@ return EINA_FALSE; } - EINA_ERROR_CONVERT_0X_NOT_FOUND = eina_error_msg_register("Error during string convertion to float, First '0x' was not found."); - EINA_ERROR_CONVERT_P_NOT_FOUND = eina_error_msg_register("Error during string convertion to float, First 'p' was not found."); - EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = eina_error_msg_register("Error outrun string limit during convertion string convertion to float."); +#define EEMR(n) n = eina_error_msg_static_register(n##_STR) + EEMR(EINA_ERROR_CONVERT_0X_NOT_FOUND); + EEMR(EINA_ERROR_CONVERT_P_NOT_FOUND); + EEMR(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH); +#undef EEMR return EINA_TRUE; } Modified: trunk/eina/src/lib/eina_counter.c =================================================================== --- trunk/eina/src/lib/eina_counter.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_counter.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -91,6 +91,7 @@ # endif } #else +static const char EINA_ERROR_COUNTER_WINDOWS_STR[] = "Change your OS, you moron !"; static int EINA_ERROR_COUNTER_WINDOWS = 0; static LARGE_INTEGER _eina_counter_frequency; @@ -249,7 +250,7 @@ eina_counter_init(void) { #ifdef _WIN32 - EINA_ERROR_COUNTER_WINDOWS = eina_error_msg_register("Change your OS, you moron !"); + EINA_ERROR_COUNTER_WINDOWS = eina_error_msg_static_register(EINA_ERROR_COUNTER_WINDOWS_STR); if (!QueryPerformanceFrequency(&_eina_counter_frequency)) { eina_error_set(EINA_ERROR_COUNTER_WINDOWS); Modified: trunk/eina/src/lib/eina_error.c =================================================================== --- trunk/eina/src/lib/eina_error.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_error.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -168,11 +168,45 @@ * @cond LOCAL */ -static const char **_eina_errors = NULL; +typedef struct _Eina_Error_Message Eina_Error_Message; +struct _Eina_Error_Message +{ + Eina_Bool string_allocated; + const char *string; +}; + +static Eina_Error_Message *_eina_errors = NULL; static size_t _eina_errors_count = 0; static size_t _eina_errors_allocated = 0; static Eina_Error _eina_last_error; +static Eina_Error_Message * +_eina_error_msg_alloc(void) +{ + size_t idx; + + if (_eina_errors_count == _eina_errors_allocated) + { + void *tmp; + size_t size; + + if (EINA_UNLIKELY(_eina_errors_allocated == 0)) + size = 24; + else + size = _eina_errors_allocated + 8; + + tmp = realloc(_eina_errors, sizeof(Eina_Error_Message) * size); + if (!tmp) + return NULL; + _eina_errors = tmp; + _eina_errors_allocated = size; + } + + idx = _eina_errors_count; + _eina_errors_count++; + return _eina_errors + idx; +} + /** * @endcond */ @@ -209,6 +243,8 @@ EAPI Eina_Error EINA_ERROR_OUT_OF_MEMORY = 0; +static const char EINA_ERROR_OUT_OF_MEMORY_STR[] = "Out of memory"; + /** * @endcond */ @@ -230,7 +266,7 @@ eina_error_init(void) { /* TODO register the eina's basic errors */ - EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_register("Out of memory"); + EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_static_register(EINA_ERROR_OUT_OF_MEMORY_STR); return EINA_TRUE; } @@ -248,11 +284,15 @@ Eina_Bool eina_error_shutdown(void) { - size_t i; + Eina_Error_Message *eem, *eem_end; - for (i = 0; i < _eina_errors_count; i++) - free((char *)_eina_errors[i]); + eem = _eina_errors; + eem_end = eem + _eina_errors_count; + for (; eem < eem_end; eem++) + if (eem->string_allocated) + free((char *)eem->string); + free(_eina_errors); _eina_errors = NULL; _eina_errors_count = 0; @@ -264,40 +304,68 @@ /** * @brief Register a new error type. * - * @param msg The description of the error. + * @param msg The description of the error. It will be duplicated using + * strdup(). * @return The unique number identifier for this error. * * This function stores in a list the error message described by * @p msg. The returned value is a unique identifier greater or equal * than 1. The description can be retrieve later by passing to * eina_error_msg_get() the returned value. + * + * @see eina_error_msg_static_register() */ EAPI Eina_Error eina_error_msg_register(const char *msg) { + Eina_Error_Message *eem; + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0); - if (_eina_errors_count == _eina_errors_allocated) + eem = _eina_error_msg_alloc(); + if (!eem) + return 0; + + eem->string_allocated = EINA_TRUE; + eem->string = strdup(msg); + if (!eem->string) { - void *tmp; - size_t size; + _eina_errors_count--; + return 0; + } - if (EINA_UNLIKELY(_eina_errors_allocated == 0)) - size = 24; - else - size = _eina_errors_allocated + 8; + return _eina_errors_count; /* identifier = index + 1 (== _count). */ +} - tmp = realloc(_eina_errors, sizeof(char *) * size); - if (!tmp) - return 0; - _eina_errors = tmp; - _eina_errors_allocated = size; - } +/** + * @brief Register a new error type, statically allocated message. + * + * @param msg The description of the error. This string will not be + * duplicated and thus the given pointer should live during + * usage of eina_error. + * @return The unique number identifier for this error. + * + * This function stores in a list the error message described by + * @p msg. The returned value is a unique identifier greater or equal + * than 1. The description can be retrieve later by passing to + * eina_error_msg_get() the returned value. + * + * @see eina_error_msg_register() + */ +EAPI Eina_Error +eina_error_msg_static_register(const char *msg) +{ + Eina_Error_Message *eem; - _eina_errors[_eina_errors_count] = strdup(msg); - if (!_eina_errors[_eina_errors_count]) + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0); + + eem = _eina_error_msg_alloc(); + if (!eem) return 0; - return ++_eina_errors_count; /* identifier = index + 1 */ + + eem->string_allocated = EINA_FALSE; + eem->string = msg; + return _eina_errors_count; /* identifier = index + 1 (== _count). */ } /** @@ -317,7 +385,7 @@ return NULL; if ((size_t)error > _eina_errors_count) return NULL; - return _eina_errors[error - 1]; + return _eina_errors[error - 1].string; } /** Modified: trunk/eina/src/lib/eina_iterator.c =================================================================== --- trunk/eina/src/lib/eina_iterator.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_iterator.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -40,6 +40,8 @@ * @cond LOCAL */ +static const char EINA_MAGIC_ITERATOR_STR[] = "Eina Iterator"; + #define EINA_MAGIC_CHECK_ITERATOR(d) \ do { \ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ITERATOR)) \ @@ -93,7 +95,7 @@ Eina_Bool eina_iterator_init(void) { - return eina_magic_string_set(EINA_MAGIC_ITERATOR, "Eina Iterator"); + return eina_magic_string_set(EINA_MAGIC_ITERATOR, EINA_MAGIC_ITERATOR_STR); } /** Modified: trunk/eina/src/lib/eina_list.c =================================================================== --- trunk/eina/src/lib/eina_list.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_list.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -90,6 +90,12 @@ * @cond LOCAL */ +static const char EINA_MAGIC_LIST_STR[] = "Eina List"; +static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator"; +static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor"; +static const char EINA_MAGIC_LIST_ACCOUNTING_STR[] = "Eina List Accounting"; + + #define EINA_MAGIC_CHECK_LIST(d, ...) \ do { \ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \ @@ -487,10 +493,12 @@ goto on_init_fail; } - 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"); - eina_magic_string_set(EINA_MAGIC_LIST_ACCOUNTING, "Eina List Accounting"); +#define EMS(n) eina_magic_string_static_set(n, n##_STR) + EMS(EINA_MAGIC_LIST); + EMS(EINA_MAGIC_LIST_ITERATOR); + EMS(EINA_MAGIC_LIST_ACCESSOR); + EMS(EINA_MAGIC_LIST_ACCOUNTING); +#undef EMS return EINA_TRUE; Modified: trunk/eina/src/lib/eina_magic.c =================================================================== --- trunk/eina/src/lib/eina_magic.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_magic.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -48,7 +48,8 @@ struct _Eina_Magic_String { Eina_Magic magic; - char *string; + Eina_Bool string_allocated; + const char *string; }; static int _eina_magic_string_log_dom = -1; @@ -76,6 +77,37 @@ return a - b->magic; } +static Eina_Magic_String * +_eina_magic_strings_alloc(void) +{ + size_t idx; + + 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 NULL; + } + _eina_magic_strings = tmp; + _eina_magic_strings_allocated = size; + } + + idx = _eina_magic_strings_count; + _eina_magic_strings_count++; + return _eina_magic_strings + idx; +} + /** * @endcond */ @@ -135,11 +167,15 @@ Eina_Bool eina_magic_string_shutdown(void) { - size_t i; + Eina_Magic_String *ems, *ems_end; - for (i = 0; i < _eina_magic_strings_count; i++) - free(_eina_magic_strings[i].string); + ems = _eina_magic_strings; + ems_end = ems + _eina_magic_strings_count; + for (; ems < ems_end; ems++) + if (ems->string_allocated) + free((char *)ems->string); + free(_eina_magic_strings); _eina_magic_strings = NULL; _eina_magic_strings_count = 0; @@ -195,6 +231,8 @@ * 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. + * + * @see eina_magic_string_static_set() */ EAPI Eina_Bool eina_magic_string_set(Eina_Magic magic, const char *magic_name) @@ -203,41 +241,59 @@ EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE); - if (_eina_magic_strings_count == _eina_magic_strings_allocated) - { - void *tmp; - size_t size; + ems = _eina_magic_strings_alloc(); + if (!ems) + return EINA_FALSE; - 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; + ems->string_allocated = EINA_TRUE; ems->string = strdup(magic_name); if (!ems->string) { ERR("could not allocate string '%s'", magic_name); + _eina_magic_strings_count--; return EINA_FALSE; } - _eina_magic_strings_count++; _eina_magic_strings_dirty = 1; return EINA_TRUE; } +/** + * @brief Set the string associated to the given magic identifier. + * + * @param magic The magic identifier. + * @param The string associated to the identifier, must not be @c NULL, + * it will not be duplcated, just referenced thus it must be live + * during magic number usage. + * + * @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. + * + * @see eina_magic_string_set() + */ +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) + return EINA_FALSE; + + ems->magic = magic; + ems->string_allocated = EINA_FALSE; + ems->string = magic_name; + + _eina_magic_strings_dirty = 1; + return EINA_TRUE; +} + #ifdef eina_magic_fail # undef eina_magic_fail #endif Modified: trunk/eina/src/lib/eina_matrixsparse.c =================================================================== --- trunk/eina/src/lib/eina_matrixsparse.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_matrixsparse.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -54,6 +54,17 @@ /** * @cond LOCAL */ + +static const char EINA_MAGIC_MATRIXSPARSE_STR[] = "Eina Matrixsparse"; +static const char EINA_MAGIC_MATRIXSPARSE_ROW_STR[] = "Eina Matrixsparse Row"; +static const char EINA_MAGIC_MATRIXSPARSE_CELL_STR[] = "Eina Matrixsparse Cell"; +static const char EINA_MAGIC_MATRIXSPARSE_ITERATOR_STR[] = "Eina Matrixsparse Iterator"; +static const char EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR_STR[] = "Eina Matrixsparse Row Accessor"; +static const char EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR_STR[] = "Eina Matrixsparse Row Iterator"; +static const char EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR_STR[] = "Eina Matrixsparse Cell Accessor"; +static const char EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR_STR[] = "Eina Matrixsparse Cell Iterator"; + + #define EINA_MAGIC_CHECK_MATRIXSPARSE(d, ...) \ do { \ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE)) \ @@ -811,14 +822,16 @@ goto on_init_fail; } - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE, "Eina Matrixsparse"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_ROW, "Eina Matrixsparse Row"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_CELL, "Eina Matrixsparse Cell"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_ITERATOR, "Eina Matrixsparse Iterator"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR, "Eina Matrixsparse Row Accessor"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR, "Eina Matrixsparse Row Iterator"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR, "Eina Matrixsparse Cell Accessor"); - eina_magic_string_set(EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR, "Eina Matrixsparse Cell Iterator"); +#define EMS(n) eina_magic_string_static_set(n, n##_STR) + EMS(EINA_MAGIC_MATRIXSPARSE); + EMS(EINA_MAGIC_MATRIXSPARSE_ROW); + EMS(EINA_MAGIC_MATRIXSPARSE_CELL); + EMS(EINA_MAGIC_MATRIXSPARSE_ITERATOR); + EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR); + EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR); + EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR); + EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR); +#undef EMS return EINA_TRUE; Modified: trunk/eina/src/lib/eina_mempool.c =================================================================== --- trunk/eina/src/lib/eina_mempool.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_mempool.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -144,6 +144,8 @@ EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0; +static const char EINA_ERROR_NOT_MEMPOOL_MODULE_STR[] = "Not a memory pool module."; + Eina_Bool eina_mempool_init(void) { @@ -156,7 +158,7 @@ return 0; } - EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_msg_register("Not a memory pool module."); + EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_msg_static_register(EINA_ERROR_NOT_MEMPOOL_MODULE_STR); _backends = eina_hash_string_superfast_new(NULL); /* dynamic backends */ Modified: trunk/eina/src/lib/eina_module.c =================================================================== --- trunk/eina/src/lib/eina_module.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_module.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -175,6 +175,9 @@ * @cond LOCAL */ +static const char EINA_ERROR_WRONG_MODULE_STR[] = "Wrong file format or no file module found"; +static const char EINA_ERROR_MODULE_INIT_FAILED_STR[] = "Module initialisation function failed"; + EAPI Eina_Error EINA_ERROR_WRONG_MODULE = 0; EAPI Eina_Error EINA_ERROR_MODULE_INIT_FAILED = 0; @@ -208,8 +211,10 @@ return EINA_FALSE; } - EINA_ERROR_WRONG_MODULE = eina_error_msg_register("Wrong file format or no file module found"); - EINA_ERROR_MODULE_INIT_FAILED = eina_error_msg_register("Module initialisation function failed"); +#define EEMR(n) n = eina_error_msg_static_register(n##_STR) + EEMR(EINA_ERROR_WRONG_MODULE); + EEMR(EINA_ERROR_MODULE_INIT_FAILED); +#undef EEMR return EINA_TRUE; } Modified: trunk/eina/src/lib/eina_safety_checks.c =================================================================== --- trunk/eina/src/lib/eina_safety_checks.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_safety_checks.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -54,6 +54,8 @@ EAPI Eina_Error EINA_ERROR_SAFETY_FAILED = 0; +static const char EINA_ERROR_SAFETY_FAILED_STR[] = "Safety check failed."; + /** * @endcond */ @@ -72,7 +74,7 @@ Eina_Bool eina_safety_checks_init(void) { - EINA_ERROR_SAFETY_FAILED = eina_error_msg_register("Safety check failed."); + EINA_ERROR_SAFETY_FAILED = eina_error_msg_static_register(EINA_ERROR_SAFETY_FAILED_STR); return EINA_TRUE; } Modified: trunk/eina/src/lib/eina_stringshare.c =================================================================== --- trunk/eina/src/lib/eina_stringshare.c 2009-09-07 02:33:54 UTC (rev 42310) +++ trunk/eina/src/lib/eina_stringshare.c 2009-09-07 03:32:22 UTC (rev 42311) @@ -95,6 +95,11 @@ #define EINA_STRINGSHARE_BUCKETS 256 #define EINA_STRINGSHARE_MASK 0xFF +static const char EINA_MAGIC_STRINGSHARE_STR[] = "Eina Stringshare"; +static const char EINA_MAGIC_STRINGSHARE_HEAD_STR[] = "Eina Stringshare Head"; +static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node"; + + #define EINA_MAGIC_CHECK_STRINGSHARE_HEAD(d, ...) \ do { \ if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_STRINGSHARE_HEAD)) \ @@ -835,9 +840,11 @@ return EINA_FALSE; } - eina_magic_string_set(EINA_MAGIC_STRINGSHARE, "Eina Stringshare"); - eina_magic_string_set(EINA_MAGIC_STRINGSHARE_HEAD, "Eina Stringshare Head"); - eina_magic_string_set(EINA_MAGIC_STRINGSHARE_NODE, "Eina Stringshare Node"); +#define EMS(n) eina_magic_string_static_set(n, n##_STR) + EMS(EINA_MAGIC_STRINGSHARE); + EMS(EINA_MAGIC_STRINGSHARE_HEAD); + EMS(EINA_MAGIC_STRINGSHARE_NODE); +#undef EMS EINA_MAGIC_SET(share, EINA_MAGIC_STRINGSHARE); _eina_stringshare_small_init(); |
From: Enlightenment S. <no-...@en...> - 2009-09-08 21:42:27
|
Log: replace UNLIKELY() with EINA_UNLIKELY() Author: barbieri Date: 2009-09-08 14:42:17 -0700 (Tue, 08 Sep 2009) New Revision: 42354 Modified: trunk/eina/src/include/eina_inline_array.x trunk/eina/src/lib/eina_array.c Modified: trunk/eina/src/include/eina_inline_array.x =================================================================== --- trunk/eina/src/include/eina_inline_array.x 2009-09-08 21:39:09 UTC (rev 42353) +++ trunk/eina/src/include/eina_inline_array.x 2009-09-08 21:42:17 UTC (rev 42354) @@ -19,11 +19,6 @@ #ifndef EINA_INLINE_ARRAY_X_ #define EINA_INLINE_ARRAY_X_ -#ifdef __GNUC__ -# define UNLIKELY(x) __builtin_expect(!!(x), 0) -#else -# define UNLIKELY(x) (x) -#endif /** * @cond LOCAL @@ -62,7 +57,7 @@ { if (!data) return EINA_FALSE; - if (UNLIKELY((array->count + 1) > array->total)) + if (EINA_UNLIKELY((array->count + 1) > array->total)) if (!eina_array_grow(array)) return EINA_FALSE; array->data[array->count++] = (void*) data; Modified: trunk/eina/src/lib/eina_array.c =================================================================== --- trunk/eina/src/lib/eina_array.c 2009-09-08 21:39:09 UTC (rev 42353) +++ trunk/eina/src/lib/eina_array.c 2009-09-08 21:42:17 UTC (rev 42354) @@ -267,7 +267,7 @@ total = array->total + array->step; eina_error_set(0); tmp = realloc(array->data, sizeof (void*) * total); - if (UNLIKELY(!tmp)) { + if (EINA_UNLIKELY(!tmp)) { eina_error_set(EINA_ERROR_OUT_OF_MEMORY); return 0; } |
From: Enlightenment S. <no-...@en...> - 2009-09-11 23:11:13
|
Log: constness++ Author: barbieri Date: 2009-09-11 16:10:57 -0700 (Fri, 11 Sep 2009) New Revision: 42426 Modified: trunk/eina/src/include/eina_tiler.h trunk/eina/src/lib/eina_tiler.c Modified: trunk/eina/src/include/eina_tiler.h =================================================================== --- trunk/eina/src/include/eina_tiler.h 2009-09-11 21:24:02 UTC (rev 42425) +++ trunk/eina/src/include/eina_tiler.h 2009-09-11 23:10:57 UTC (rev 42426) @@ -28,8 +28,8 @@ EAPI Eina_Tiler *eina_tiler_new(int w, int h); EAPI void eina_tiler_free(Eina_Tiler *t); EAPI void eina_tiler_tile_size_set(Eina_Tiler *t, int w, int h); -EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, Eina_Rectangle *r); -EAPI void eina_tiler_rect_del(Eina_Tiler *t, Eina_Rectangle *r); +EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, const Eina_Rectangle *r); +EAPI void eina_tiler_rect_del(Eina_Tiler *t, const Eina_Rectangle *r); EAPI void eina_tiler_clear(Eina_Tiler *t); EAPI Eina_Iterator * eina_tiler_iterator_new(const Eina_Tiler *t); Modified: trunk/eina/src/lib/eina_tiler.c =================================================================== --- trunk/eina/src/lib/eina_tiler.c 2009-09-11 21:24:02 UTC (rev 42425) +++ trunk/eina/src/lib/eina_tiler.c 2009-09-11 23:10:57 UTC (rev 42426) @@ -1140,7 +1140,7 @@ * To be documented * FIXME: To be fixed */ -EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, Eina_Rectangle *r) +EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, const Eina_Rectangle *r) { Eina_Rectangle tmp; @@ -1158,7 +1158,7 @@ * To be documented * FIXME: To be fixed */ -EAPI void eina_tiler_rect_del(Eina_Tiler *t, Eina_Rectangle *r) +EAPI void eina_tiler_rect_del(Eina_Tiler *t, const Eina_Rectangle *r) { Eina_Rectangle tmp; |
From: Enlightenment S. <no-...@en...> - 2009-11-23 13:20:45
|
Log: eina_module_find: constness and gcc attribute. Mark both array and module as const as we'll not modify them anyhow inside this function. Also mark this function as pure, so gcc will know how to optimize multiple calls of it. Not that important for this function, but doesn't hurt either. Author: barbieri Date: 2009-11-23 05:20:34 -0800 (Mon, 23 Nov 2009) New Revision: 43918 Modified: trunk/eina/src/include/eina_module.h trunk/eina/src/lib/eina_module.c Modified: trunk/eina/src/include/eina_module.h =================================================================== --- trunk/eina/src/include/eina_module.h 2009-11-23 10:07:07 UTC (rev 43917) +++ trunk/eina/src/include/eina_module.h 2009-11-23 13:20:34 UTC (rev 43918) @@ -70,7 +70,7 @@ EAPI void eina_module_list_load(Eina_Array *list) EINA_ARG_NONNULL(1); EAPI void eina_module_list_unload(Eina_Array *list) EINA_ARG_NONNULL(1); EAPI void eina_module_list_flush(Eina_Array *list) EINA_ARG_NONNULL(1); -EAPI Eina_Module * eina_module_find(Eina_Array *array, char *module) EINA_ARG_NONNULL(1, 2); +EAPI Eina_Module * eina_module_find(const Eina_Array *array, const char *module) EINA_ARG_NONNULL(1, 2) EINA_PURE; /** * @} Modified: trunk/eina/src/lib/eina_module.c =================================================================== --- trunk/eina/src/lib/eina_module.c 2009-11-23 10:07:07 UTC (rev 43917) +++ trunk/eina/src/lib/eina_module.c 2009-11-23 13:20:34 UTC (rev 43918) @@ -556,7 +556,7 @@ * If the element is found return the module else NULL. */ EAPI Eina_Module * -eina_module_find(Eina_Array *array, char *module) +eina_module_find(const Eina_Array *array, const char *module) { unsigned int i; Eina_Array_Iterator iterator; |
From: Enlightenment S. <no-...@en...> - 2009-11-23 13:24:57
|
Log: eina_module: more constness. Thanks to Fabiano Fidencio for spotting those. Author: barbieri Date: 2009-11-23 05:24:48 -0800 (Mon, 23 Nov 2009) New Revision: 43921 Modified: trunk/eina/src/include/eina_module.h trunk/eina/src/lib/eina_module.c Modified: trunk/eina/src/include/eina_module.h =================================================================== --- trunk/eina/src/include/eina_module.h 2009-11-23 13:21:35 UTC (rev 43920) +++ trunk/eina/src/include/eina_module.h 2009-11-23 13:24:48 UTC (rev 43921) @@ -60,8 +60,8 @@ EAPI Eina_Bool eina_module_free(Eina_Module *m) EINA_ARG_NONNULL(1); EAPI Eina_Bool eina_module_load(Eina_Module *module) EINA_ARG_NONNULL(1); EAPI Eina_Bool eina_module_unload(Eina_Module *m) EINA_ARG_NONNULL(1); -EAPI void *eina_module_symbol_get(Eina_Module *module, const char *symbol) EINA_PURE EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT; -EAPI const char * eina_module_file_get(Eina_Module *m) EINA_PURE EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); +EAPI void *eina_module_symbol_get(const Eina_Module *module, const char *symbol) EINA_PURE EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT; +EAPI const char * eina_module_file_get(const Eina_Module *m) EINA_PURE EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); EAPI char *eina_module_symbol_path_get(const void *symbol, const char *sub_dir) EINA_PURE EINA_MALLOC EINA_ARG_NONNULL(1, 2); EAPI char *eina_module_environment_path_get(const char *env, const char *sub_dir) EINA_PURE EINA_MALLOC EINA_ARG_NONNULL(1, 2); Modified: trunk/eina/src/lib/eina_module.c =================================================================== --- trunk/eina/src/lib/eina_module.c 2009-11-23 13:21:35 UTC (rev 43920) +++ trunk/eina/src/lib/eina_module.c 2009-11-23 13:24:48 UTC (rev 43921) @@ -426,7 +426,7 @@ * is @c NULL, or if it has not been correctly loaded before, the * function returns immediatly @c NULL. */ -EAPI void * eina_module_symbol_get(Eina_Module *m, const char *symbol) +EAPI void * eina_module_symbol_get(const Eina_Module *m, const char *symbol) { EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(m->handle, NULL); @@ -443,7 +443,7 @@ * @c NULL, the function returns immediatly @c NULL. The returned * value must no be freed. */ -EAPI const char * eina_module_file_get(Eina_Module *m) +EAPI const char * eina_module_file_get(const Eina_Module *m) { EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); return m->file; |