From 80a227ff137ba25656a6f47506f1261f4184673b Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 19 Sep 2008 12:19:06 +0000 Subject: [PATCH] We have now a defined behaviour when we have more than one entry with the same key in the hash table. SVN revision: 36096 --- legacy/eina/src/lib/eina_hash.c | 36 +++++++++++++++++++++----- legacy/eina/src/tests/eina_test_hash.c | 25 ++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/legacy/eina/src/lib/eina_hash.c b/legacy/eina/src/lib/eina_hash.c index 202fe82031..162a6f1dfc 100644 --- a/legacy/eina/src/lib/eina_hash.c +++ b/legacy/eina/src/lib/eina_hash.c @@ -100,9 +100,15 @@ struct _Eina_Hash_Each #endif static inline int -_eina_hash_rbtree_key(const Eina_Hash_El *el, const char *key, int key_length, Eina_Key_Cmp cmp) +_eina_hash_rbtree_key(const Eina_Hash_El *el, const Eina_Hash_Tuple *tuple, __UNUSED__ int key_length, Eina_Key_Cmp cmp) { - return cmp(el->tuple.key, el->tuple.key_length, key, key_length); + int result; + + result = cmp(el->tuple.key, el->tuple.key_length, tuple->key, tuple->key_length); + if (result == 0) + if (tuple->data && el->tuple.data != tuple->data) + return 1; + return result; } static Eina_Rbtree_Direction @@ -125,13 +131,13 @@ _eina_hash_rbtree_each(__UNUSED__ const Eina_Rbtree *container, const Eina_Hash_ } static inline Eina_Hash_El * -_eina_hash_find_by_hash(const Eina_Hash *hash, const char *key, int key_length, int key_hash) +_eina_hash_find_by_hash(const Eina_Hash *hash, Eina_Hash_Tuple *tuple, int key_hash) { Eina_Hash_El *el; key_hash &= 0xFF; - el = (Eina_Hash_El*) eina_rbtree_inline_lookup(hash->buckets[key_hash], key, key_length, EINA_RBTREE_CMP_KEY_CB(_eina_hash_rbtree_key), hash->key_cmp_cb); + el = (Eina_Hash_El*) eina_rbtree_inline_lookup(hash->buckets[key_hash], tuple, sizeof (Eina_Hash_Tuple), EINA_RBTREE_CMP_KEY_CB(_eina_hash_rbtree_key), hash->key_cmp_cb); return el; } @@ -647,12 +653,18 @@ 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_El *el = NULL; + Eina_Hash_Tuple tuple; + + tuple.key = (void *) key; + tuple.key_length = key_length; + tuple.data = (void *) data; if (!hash) return EINA_FALSE; if (!key) el = _eina_hash_find_by_data(hash, data, &key_hash); - else el = _eina_hash_find_by_hash(hash, key, key_length, key_hash); + else el = _eina_hash_find_by_hash(hash, &tuple, key_hash); if (!el) return EINA_FALSE; + if (data && el->tuple.data != data) return EINA_FALSE; key_hash &= 0xFF; @@ -706,10 +718,15 @@ EAPI void * eina_hash_find_by_hash(const Eina_Hash *hash, const void *key, int key_length, int key_hash) { Eina_Hash_El *el; + Eina_Hash_Tuple tuple; if ((!hash) || (!key)) return NULL; - el = _eina_hash_find_by_hash(hash, key, key_length, key_hash); + tuple.key = key; + tuple.key_length = key_length; + tuple.data = NULL; + + el = _eina_hash_find_by_hash(hash, &tuple, key_hash); if (el) return el->tuple.data; return NULL; } @@ -751,10 +768,15 @@ eina_hash_modify_by_hash(Eina_Hash *hash, const void *key, int key_length, int k { Eina_Hash_El *el; void *old_data = NULL; + Eina_Hash_Tuple tuple; if (!hash) return NULL; - el = _eina_hash_find_by_hash(hash, key, key_length, key_hash); + tuple.key = key; + tuple.key_length = key_length; + tuple.data = NULL; + + el = _eina_hash_find_by_hash(hash, &tuple, key_hash); if (el) { old_data = el->tuple.data; diff --git a/legacy/eina/src/tests/eina_test_hash.c b/legacy/eina/src/tests/eina_test_hash.c index 42d4285e18..2de244ed27 100644 --- a/legacy/eina/src/tests/eina_test_hash.c +++ b/legacy/eina/src/tests/eina_test_hash.c @@ -138,9 +138,34 @@ START_TEST(eina_hash_extended) } END_TEST +START_TEST(eina_hash_double_item) +{ + Eina_Hash *hash = NULL; + int i[] = { 7, 7 }; + int *test; + + fail_if(eina_hash_init() <= 0); + + hash = eina_hash_string_superfast_new(); + fail_if(hash == NULL); + + fail_if(eina_hash_add(hash, "7", &i[0]) != EINA_TRUE); + fail_if(eina_hash_add(hash, "7", &i[1]) != EINA_TRUE); + + fail_if(eina_hash_del(hash, "7", &i[1]) != EINA_TRUE); + test = eina_hash_find(hash, "7"); + fail_if(test != &i[0]); + + eina_hash_free(hash); + + fail_if(eina_hash_shutdown() > 0); +} +END_TEST + void eina_test_hash(TCase *tc) { tcase_add_test(tc, eina_hash_init_shutdown); tcase_add_test(tc, eina_hash_simple); tcase_add_test(tc, eina_hash_extended); + tcase_add_test(tc, eina_hash_double_item); }