forked from enlightenment/efl
hash: better handling of NULL, add magic checking.
* evas: if we automatically destroy hash, check for NULL before handling it to eina api, which expect elements to be created with eina_hash_new() and thus will fail on NULL. * eina: add magic checking for eina_hash and eina_hash_iterator, this will help spot when NULL is used. * eina_hash_foreach: do not try to create the iterator if hash is NULL. SVN revision: 37982
This commit is contained in:
parent
7dfff8ac98
commit
8ea28f64b7
|
@ -63,6 +63,9 @@
|
|||
#define EINA_MAGIC_ARRAY_ITERATOR 0x9876123c
|
||||
#define EINA_MAGIC_ARRAY_ACCESSOR 0x9876123d
|
||||
|
||||
#define EINA_MAGIC_HASH 0x9876123e
|
||||
#define EINA_MAGIC_HASH_ITERATOR 0x9876123f
|
||||
|
||||
/* undef the following, we want out version */
|
||||
#undef FREE
|
||||
#define FREE(ptr) \
|
||||
|
|
|
@ -38,6 +38,18 @@
|
|||
* @cond LOCAL
|
||||
*/
|
||||
|
||||
#define EINA_MAGIC_CHECK_HASH(d) \
|
||||
do { \
|
||||
if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH)) \
|
||||
EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH); \
|
||||
} while(0)
|
||||
|
||||
#define EINA_MAGIC_CHECK_HASH_ITERATOR(d) \
|
||||
do { \
|
||||
if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH_ITERATOR)) \
|
||||
EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH_ITERATOR); \
|
||||
} while(0)
|
||||
|
||||
#define EINA_HASH_BUCKET_SIZE 256
|
||||
#define EINA_HASH_BUCKET_MASK 0xFF
|
||||
#define EINA_HASH_RBTREE_MASK 0xFFF
|
||||
|
@ -57,6 +69,8 @@ struct _Eina_Hash
|
|||
|
||||
Eina_Rbtree *buckets[EINA_HASH_BUCKET_SIZE];
|
||||
int population;
|
||||
|
||||
EINA_MAGIC;
|
||||
};
|
||||
|
||||
struct _Eina_Hash_Head
|
||||
|
@ -97,6 +111,8 @@ struct _Eina_Iterator_Hash
|
|||
int bucket;
|
||||
|
||||
int index;
|
||||
|
||||
EINA_MAGIC;
|
||||
};
|
||||
|
||||
struct _Eina_Hash_Each
|
||||
|
@ -169,6 +185,7 @@ eina_hash_add_alloc_by_hash(Eina_Hash *hash,
|
|||
Eina_Error error = 0;
|
||||
int hash_num;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if ((!hash) || (!key) || (!data)) goto on_error;
|
||||
error = EINA_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -341,6 +358,7 @@ _eina_foreach_cb(const Eina_Hash *hash, Eina_Hash_Tuple *data, Eina_Hash_Foreach
|
|||
static void *
|
||||
_eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it)
|
||||
{
|
||||
EINA_MAGIC_CHECK_HASH_ITERATOR(it);
|
||||
Eina_Hash_El *stuff = it->el;
|
||||
|
||||
if (!stuff) return NULL;
|
||||
|
@ -350,6 +368,7 @@ _eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it)
|
|||
static void *
|
||||
_eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it)
|
||||
{
|
||||
EINA_MAGIC_CHECK_HASH_ITERATOR(it);
|
||||
Eina_Hash_El *stuff = it->el;
|
||||
|
||||
if (!stuff) return NULL;
|
||||
|
@ -359,6 +378,7 @@ _eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it)
|
|||
static Eina_Hash_Tuple *
|
||||
_eina_hash_iterator_tuple_get_content(Eina_Iterator_Hash *it)
|
||||
{
|
||||
EINA_MAGIC_CHECK_HASH_ITERATOR(it);
|
||||
Eina_Hash_El *stuff = it->el;
|
||||
|
||||
if (!stuff) return NULL;
|
||||
|
@ -435,12 +455,14 @@ _eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data)
|
|||
static void *
|
||||
_eina_hash_iterator_get_container(Eina_Iterator_Hash *it)
|
||||
{
|
||||
EINA_MAGIC_CHECK_HASH_ITERATOR(it);
|
||||
return (void *) it->hash;
|
||||
}
|
||||
|
||||
static void
|
||||
_eina_hash_iterator_free(Eina_Iterator_Hash *it)
|
||||
{
|
||||
EINA_MAGIC_CHECK_HASH_ITERATOR(it);
|
||||
if (it->current) eina_iterator_free(it->current);
|
||||
if (it->list) eina_iterator_free(it->list);
|
||||
free(it);
|
||||
|
@ -556,6 +578,8 @@ eina_hash_new(Eina_Key_Length key_length_cb,
|
|||
|
||||
memset(new->buckets, 0, sizeof (new->buckets));
|
||||
|
||||
EINA_MAGIC_SET(new, EINA_MAGIC_HASH);
|
||||
|
||||
return new;
|
||||
|
||||
on_error:
|
||||
|
@ -589,6 +613,7 @@ eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb)
|
|||
EAPI int
|
||||
eina_hash_population(const Eina_Hash *hash)
|
||||
{
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return 0;
|
||||
return hash->population;
|
||||
}
|
||||
|
@ -616,6 +641,7 @@ eina_hash_free(Eina_Hash *hash)
|
|||
{
|
||||
int i;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return;
|
||||
|
||||
for (i = 0; i < EINA_HASH_BUCKET_SIZE; i++)
|
||||
|
@ -713,6 +739,7 @@ eina_hash_add(Eina_Hash *hash, const void *key, const void *data)
|
|||
unsigned int key_length;
|
||||
int key_hash;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if ((!hash) || (!key) || (!data)) return EINA_FALSE;
|
||||
|
||||
key_length = hash->key_length_cb(key);
|
||||
|
@ -747,6 +774,7 @@ eina_hash_direct_add(Eina_Hash *hash, const void *key, const void *data)
|
|||
int key_length;
|
||||
int key_hash;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if ((!hash) || (!key) || (!data)) return EINA_FALSE;
|
||||
|
||||
key_length = hash->key_length_cb(key);
|
||||
|
@ -795,6 +823,7 @@ eina_hash_del_by_key_hash(Eina_Hash *hash, const void *key, int key_length, int
|
|||
Eina_Hash_Head *eh;
|
||||
Eina_Hash_Tuple tuple;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return EINA_FALSE;
|
||||
if (!key) return EINA_FALSE;
|
||||
|
||||
|
@ -826,6 +855,7 @@ eina_hash_del_by_key(Eina_Hash *hash, const void *key)
|
|||
{
|
||||
int key_length, key_hash;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return EINA_FALSE;
|
||||
if (!key) return EINA_FALSE;
|
||||
|
||||
|
@ -853,6 +883,7 @@ eina_hash_del_by_data(Eina_Hash *hash, const void *data)
|
|||
Eina_Hash_Head *eh;
|
||||
int key_hash;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return EINA_FALSE;
|
||||
if (!data) return EINA_FALSE;
|
||||
|
||||
|
@ -931,6 +962,7 @@ eina_hash_find_by_hash(const Eina_Hash *hash, const void *key, int key_length, i
|
|||
Eina_Hash_El *el;
|
||||
Eina_Hash_Tuple tuple;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if ((!hash) || (!key)) return NULL;
|
||||
|
||||
tuple.key = key;
|
||||
|
@ -955,6 +987,7 @@ eina_hash_find(const Eina_Hash *hash, const void *key)
|
|||
int key_length;
|
||||
int hash_num;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if ((!hash) || (!key)) return NULL;
|
||||
|
||||
key_length = hash->key_length_cb(key);
|
||||
|
@ -982,8 +1015,8 @@ eina_hash_modify_by_hash(Eina_Hash *hash, const void *key, int key_length, int k
|
|||
void *old_data = NULL;
|
||||
Eina_Hash_Tuple tuple;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return NULL;
|
||||
|
||||
tuple.key = key;
|
||||
tuple.key_length = key_length;
|
||||
tuple.data = NULL;
|
||||
|
@ -1013,6 +1046,7 @@ eina_hash_modify(Eina_Hash *hash, const void *key, const void *data)
|
|||
int key_length;
|
||||
int hash_num;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return NULL;
|
||||
|
||||
key_length = hash->key_length_cb(key);
|
||||
|
@ -1065,6 +1099,9 @@ eina_hash_foreach(const Eina_Hash *hash,
|
|||
Eina_Iterator *it;
|
||||
Eina_Hash_Foreach_Data foreach;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return;
|
||||
|
||||
foreach.cb = func;
|
||||
foreach.fdata = fdata;
|
||||
|
||||
|
@ -1078,6 +1115,7 @@ eina_hash_iterator_data_new(const Eina_Hash *hash)
|
|||
{
|
||||
Eina_Iterator_Hash *it;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return NULL;
|
||||
if (hash->population <= 0) return NULL;
|
||||
|
||||
|
@ -1092,6 +1130,7 @@ eina_hash_iterator_data_new(const Eina_Hash *hash)
|
|||
it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
|
||||
|
||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||
EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
|
||||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
@ -1101,6 +1140,7 @@ eina_hash_iterator_key_new(const Eina_Hash *hash)
|
|||
{
|
||||
Eina_Iterator_Hash *it;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return NULL;
|
||||
if (hash->population <= 0) return NULL;
|
||||
|
||||
|
@ -1115,6 +1155,7 @@ eina_hash_iterator_key_new(const Eina_Hash *hash)
|
|||
it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
|
||||
|
||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||
EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
|
||||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
@ -1124,6 +1165,7 @@ eina_hash_iterator_tuple_new(const Eina_Hash *hash)
|
|||
{
|
||||
Eina_Iterator_Hash *it;
|
||||
|
||||
EINA_MAGIC_CHECK_HASH(hash);
|
||||
if (!hash) return NULL;
|
||||
if (hash->population <= 0) return NULL;
|
||||
|
||||
|
@ -1138,6 +1180,7 @@ eina_hash_iterator_tuple_new(const Eina_Hash *hash)
|
|||
it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
|
||||
|
||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||
EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
|
||||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
|
|
@ -102,10 +102,29 @@ extern "C" {
|
|||
return 255;
|
||||
}
|
||||
|
||||
#define evas_hash_find eina_hash_find
|
||||
#define evas_hash_modify eina_hash_modify
|
||||
#define evas_hash_free eina_hash_free
|
||||
#define evas_hash_foreach eina_hash_foreach
|
||||
static inline void *evas_hash_find(const Eina_Hash *hash, const void *key)
|
||||
{
|
||||
if (!hash) return NULL;
|
||||
return eina_hash_find(hash, key);
|
||||
}
|
||||
|
||||
static inline void *evas_hash_modify(Eina_Hash *hash, const void *key, const void *data)
|
||||
{
|
||||
if (!hash) return NULL;
|
||||
return eina_hash_modify(hash, key, data);
|
||||
}
|
||||
static inline void evas_hash_free(Eina_Hash *hash)
|
||||
{
|
||||
if (!hash) return NULL;
|
||||
return eina_hash_free(hash);
|
||||
}
|
||||
|
||||
static inline void evas_hash_foreach(const Eina_Hash *hash, Eina_Hash_Foreach cb, const void *fdata)
|
||||
{
|
||||
if (!hash) return;
|
||||
eina_hash_foreach(hash, cb, fdata);
|
||||
}
|
||||
|
||||
#define evas_hash_alloc_error eina_error_get
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue