1 /* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri,
3 * Vincent Torri, Jorge Luis Zapata Muga, Cedric Bail
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library;
17 * if not, see <http://www.gnu.org/licenses/>.
36 #include "eina_config.h"
37 #include "eina_private.h"
38 #include "eina_rbtree.h"
39 #include "eina_error.h"
41 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
42 #include "eina_safety_checks.h"
43 #include "eina_hash.h"
45 /*============================================================================*
47 *============================================================================*/
53 #define EINA_MAGIC_CHECK_HASH(d) \
55 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH)) { \
56 EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH); } \
59 #define EINA_MAGIC_CHECK_HASH_ITERATOR(d, ...) \
61 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH_ITERATOR)) \
63 EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH_ITERATOR); \
68 #define EINA_HASH_BUCKET_SIZE 8
69 #define EINA_HASH_SMALL_BUCKET_SIZE 5
71 #define EINA_HASH_RBTREE_MASK 0xFFF
73 typedef struct _Eina_Hash_Head Eina_Hash_Head;
74 typedef struct _Eina_Hash_Element Eina_Hash_Element;
75 typedef struct _Eina_Hash_Foreach_Data Eina_Hash_Foreach_Data;
76 typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash;
77 typedef struct _Eina_Hash_Each Eina_Hash_Each;
81 Eina_Key_Length key_length_cb;
82 Eina_Key_Cmp key_cmp_cb;
83 Eina_Key_Hash key_hash_cb;
84 Eina_Free_Cb data_free_cb;
86 Eina_Rbtree **buckets;
95 struct _Eina_Hash_Head
103 struct _Eina_Hash_Element
106 Eina_Hash_Tuple tuple;
110 struct _Eina_Hash_Foreach_Data
112 Eina_Hash_Foreach cb;
116 typedef void *(*Eina_Iterator_Get_Content_Callback)(Eina_Iterator_Hash *it);
117 #define FUNC_ITERATOR_GET_CONTENT(Function) \
118 ((Eina_Iterator_Get_Content_Callback)Function)
120 struct _Eina_Iterator_Hash
122 Eina_Iterator iterator;
124 Eina_Iterator_Get_Content_Callback get_content;
125 const Eina_Hash *hash;
127 Eina_Iterator *current;
129 Eina_Hash_Head *hash_head;
130 Eina_Hash_Element *hash_element;
138 struct _Eina_Hash_Each
140 Eina_Hash_Head *hash_head;
141 const Eina_Hash_Element *hash_element;
146 #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
147 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
148 # define get16bits(d) (*((const uint16_t *)(d)))
151 #if !defined (get16bits)
152 # define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
153 + (uint32_t)(((const uint8_t *)(d))[0]))
157 _eina_hash_hash_rbtree_cmp_hash(const Eina_Hash_Head *hash_head,
159 __UNUSED__ int key_length,
160 __UNUSED__ void *data)
162 return hash_head->hash - *hash;
165 static Eina_Rbtree_Direction
166 _eina_hash_hash_rbtree_cmp_node(const Eina_Hash_Head *left,
167 const Eina_Hash_Head *right,
168 __UNUSED__ void *data)
170 if (left->hash - right->hash < 0)
171 return EINA_RBTREE_LEFT;
173 return EINA_RBTREE_RIGHT;
177 _eina_hash_key_rbtree_cmp_key_data(const Eina_Hash_Element *hash_element,
178 const Eina_Hash_Tuple *tuple,
179 __UNUSED__ unsigned int key_length,
184 result = cmp(hash_element->tuple.key,
185 hash_element->tuple.key_length,
189 if (result == 0 && tuple->data && tuple->data != hash_element->tuple.data)
195 static Eina_Rbtree_Direction
196 _eina_hash_key_rbtree_cmp_node(const Eina_Hash_Element *left,
197 const Eina_Hash_Element *right,
202 result = cmp(left->tuple.key, left->tuple.key_length,
203 right->tuple.key, right->tuple.key_length);
206 return EINA_RBTREE_LEFT;
208 return EINA_RBTREE_RIGHT;
211 static inline Eina_Bool
212 eina_hash_add_alloc_by_hash(Eina_Hash *hash,
213 const void *key, int key_length, int alloc_length,
217 Eina_Hash_Element *new_hash_element = NULL;
218 Eina_Hash_Head *hash_head;
219 Eina_Error error = 0;
222 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
223 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
224 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
225 EINA_MAGIC_CHECK_HASH(hash);
227 error = EINA_ERROR_OUT_OF_MEMORY;
229 /* Apply eina mask to hash. */
230 hash_num = key_hash & hash->mask;
231 key_hash &= EINA_HASH_RBTREE_MASK;
235 hash->buckets = calloc(sizeof (Eina_Rbtree *), hash->size);
236 if (!hash->buckets) goto on_error;
241 /* Look up for head node. */
242 hash_head = (Eina_Hash_Head *)
243 eina_rbtree_inline_lookup(hash->buckets[hash_num],
245 EINA_RBTREE_CMP_KEY_CB(
246 _eina_hash_hash_rbtree_cmp_hash),
251 /* If not found allocate it and an element. */
252 hash_head = malloc(sizeof(Eina_Hash_Head) + sizeof(Eina_Hash_Element)
257 hash_head->hash = key_hash;
258 hash_head->head = NULL;
260 hash->buckets[hash_num] =
261 eina_rbtree_inline_insert(hash->buckets[hash_num],
262 EINA_RBTREE_GET(hash_head),
263 EINA_RBTREE_CMP_NODE_CB(
264 _eina_hash_hash_rbtree_cmp_node),
267 new_hash_element = (Eina_Hash_Element *)(hash_head + 1);
268 new_hash_element->begin = EINA_TRUE;
271 if (!new_hash_element)
275 (No more lookup as we expect to support more than one item for one key).
277 new_hash_element = malloc(sizeof (Eina_Hash_Element) + alloc_length);
278 if (!new_hash_element)
281 new_hash_element->begin = EINA_FALSE;
284 /* Setup the element */
285 new_hash_element->tuple.key_length = key_length;
286 new_hash_element->tuple.data = (void *)data;
287 if (alloc_length > 0)
289 new_hash_element->tuple.key = (char *)(new_hash_element + 1);
290 memcpy((char *)new_hash_element->tuple.key, key, alloc_length);
293 new_hash_element->tuple.key = key;
295 /* add the new element to the hash. */
296 hash_head->head = eina_rbtree_inline_insert(hash_head->head,
297 EINA_RBTREE_GET(new_hash_element),
298 EINA_RBTREE_CMP_NODE_CB(
299 _eina_hash_key_rbtree_cmp_node),
300 (const void *)hash->key_cmp_cb);
305 eina_error_set(error);
310 _eina_hash_rbtree_each(__UNUSED__ const Eina_Rbtree *container,
311 const Eina_Hash_Head *hash_head,
312 Eina_Hash_Each *data)
315 Eina_Hash_Element *hash_element;
316 Eina_Bool found = EINA_TRUE;
318 it = eina_rbtree_iterator_prefix(hash_head->head);
319 EINA_ITERATOR_FOREACH(it, hash_element)
321 if (hash_element->tuple.data == data->data)
323 data->hash_element = hash_element;
324 data->hash_head = (Eina_Hash_Head *)hash_head;
330 eina_iterator_free(it);
334 static inline Eina_Hash_Element *
335 _eina_hash_find_by_hash(const Eina_Hash *hash,
336 Eina_Hash_Tuple *tuple,
338 Eina_Hash_Head **hash_head)
340 Eina_Hash_Element *hash_element;
341 int rb_hash = key_hash & EINA_HASH_RBTREE_MASK;
343 key_hash &= hash->mask;
348 *hash_head = (Eina_Hash_Head *)
349 eina_rbtree_inline_lookup(hash->buckets[key_hash],
351 EINA_RBTREE_CMP_KEY_CB(
352 _eina_hash_hash_rbtree_cmp_hash),
357 hash_element = (Eina_Hash_Element *)
358 eina_rbtree_inline_lookup((*hash_head)->head,
360 EINA_RBTREE_CMP_KEY_CB(
361 _eina_hash_key_rbtree_cmp_key_data),
362 (const void *)hash->key_cmp_cb);
367 static inline Eina_Hash_Element *
368 _eina_hash_find_by_data(const Eina_Hash *hash,
371 Eina_Hash_Head **hash_head)
380 each.hash_element = NULL;
383 for (hash_num = 0; hash_num < hash->size; hash_num++)
385 if (!hash->buckets[hash_num])
388 it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]);
389 eina_iterator_foreach(it, EINA_EACH_CB(_eina_hash_rbtree_each), &each);
390 eina_iterator_free(it);
392 if (each.hash_element)
394 *key_hash = hash_num;
395 *hash_head = each.hash_head;
396 return (Eina_Hash_Element *)each.hash_element;
404 _eina_hash_el_free(Eina_Hash_Element *hash_element, Eina_Hash *hash)
406 if (hash->data_free_cb)
407 hash->data_free_cb(hash_element->tuple.data);
409 if (hash_element->begin == EINA_FALSE)
414 _eina_hash_head_free(Eina_Hash_Head *hash_head, Eina_Hash *hash)
416 eina_rbtree_delete(hash_head->head, EINA_RBTREE_FREE_CB(_eina_hash_el_free), hash);
421 _eina_hash_del_by_hash_el(Eina_Hash *hash,
422 Eina_Hash_Element *hash_element,
423 Eina_Hash_Head *hash_head,
426 hash_head->head = eina_rbtree_inline_remove(hash_head->head, EINA_RBTREE_GET(
427 hash_element), EINA_RBTREE_CMP_NODE_CB(
428 _eina_hash_key_rbtree_cmp_node),
429 (const void *)hash->key_cmp_cb);
430 _eina_hash_el_free(hash_element, hash);
432 if (!hash_head->head)
434 key_hash &= hash->mask;
436 hash->buckets[key_hash] =
437 eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET(
439 EINA_RBTREE_CMP_NODE_CB(
440 _eina_hash_hash_rbtree_cmp_node), NULL);
445 if (hash->population == 0)
448 hash->buckets = NULL;
455 _eina_hash_del_by_key_hash(Eina_Hash *hash,
461 Eina_Hash_Element *hash_element;
462 Eina_Hash_Head *hash_head;
463 Eina_Hash_Tuple tuple;
465 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
466 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
467 EINA_MAGIC_CHECK_HASH(hash);
472 tuple.key = (void *)key;
473 tuple.key_length = key_length;
474 tuple.data = (void *)data;
476 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
480 return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
484 _eina_hash_del_by_key(Eina_Hash *hash, const void *key, const void *data)
486 int key_length, key_hash;
488 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
489 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
490 EINA_MAGIC_CHECK_HASH(hash);
495 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
496 key_hash = hash->key_hash_cb(key, key_length);
497 return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data);
501 _eina_string_key_length(const char *key)
506 return (int)strlen(key) + 1;
510 _eina_string_key_cmp(const char *key1, __UNUSED__ int key1_length,
511 const char *key2, __UNUSED__ int key2_length)
513 return strcmp(key1, key2);
517 _eina_stringshared_key_cmp(const char *key1, __UNUSED__ int key1_length,
518 const char *key2, __UNUSED__ int key2_length)
524 _eina_int32_key_length(__UNUSED__ const uint32_t *key)
530 _eina_int32_key_cmp(const uint32_t *key1, __UNUSED__ int key1_length,
531 const uint32_t *key2, __UNUSED__ int key2_length)
533 return *key1 - *key2;
537 _eina_int64_key_length(__UNUSED__ const uint32_t *key)
543 _eina_int64_key_cmp(const uint64_t *key1, __UNUSED__ int key1_length,
544 const uint64_t *key2, __UNUSED__ int key2_length)
546 return *key1 - *key2;
550 _eina_foreach_cb(const Eina_Hash *hash,
551 Eina_Hash_Tuple *data,
552 Eina_Hash_Foreach_Data *fdata)
554 return fdata->cb((Eina_Hash *)hash,
557 (void *)fdata->fdata);
561 _eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it)
563 Eina_Hash_Element *stuff;
565 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
567 stuff = it->hash_element;
572 return stuff->tuple.data;
576 _eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it)
578 Eina_Hash_Element *stuff;
580 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
582 stuff = it->hash_element;
587 return (void *)stuff->tuple.key;
590 static Eina_Hash_Tuple *
591 _eina_hash_iterator_tuple_get_content(Eina_Iterator_Hash *it)
593 Eina_Hash_Element *stuff;
595 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
597 stuff = it->hash_element;
602 return &stuff->tuple;
606 _eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data)
611 if (!(it->index < it->hash->population))
622 ok = eina_iterator_next(it->list, (void **)(void *)&it->hash_element);
625 eina_iterator_free(it->list);
628 ok = eina_iterator_next(it->current, (void **)(void *)&it->hash_head);
631 eina_iterator_free(it->current);
637 it->list = eina_rbtree_iterator_prefix(it->hash_head->head);
638 ok = eina_iterator_next(it->list, (void **)(void *)&it->hash_element);
645 if (ok == EINA_FALSE)
647 while (bucket < it->hash->size)
649 if (it->hash->buckets[bucket])
652 eina_rbtree_iterator_prefix(it->hash->buckets[bucket]);
653 ok = eina_iterator_next(it->current, (void **)(void *)&it->hash_head);
657 eina_iterator_free(it->current);
664 eina_iterator_free(it->list);
666 it->list = eina_rbtree_iterator_prefix(it->hash_head->head);
667 ok = eina_iterator_next(it->list, (void **)(void *)&it->hash_element);
668 if (bucket == it->hash->size)
676 *data = it->get_content(it);
682 _eina_hash_iterator_get_container(Eina_Iterator_Hash *it)
684 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
685 return (void *)it->hash;
689 _eina_hash_iterator_free(Eina_Iterator_Hash *it)
691 EINA_MAGIC_CHECK_HASH_ITERATOR(it);
693 eina_iterator_free(it->current);
696 eina_iterator_free(it->list);
705 /*============================================================================*
707 *============================================================================*/
709 /*============================================================================*
711 *============================================================================*/
714 eina_hash_free_cb_set(Eina_Hash *hash, Eina_Free_Cb data_free_cb)
716 EINA_MAGIC_CHECK_HASH(hash);
717 EINA_SAFETY_ON_NULL_RETURN(hash);
719 hash->data_free_cb = data_free_cb;
723 eina_hash_new(Eina_Key_Length key_length_cb,
724 Eina_Key_Cmp key_cmp_cb,
725 Eina_Key_Hash key_hash_cb,
726 Eina_Free_Cb data_free_cb,
727 int buckets_power_size)
729 /* FIXME: Use mempool. */
733 EINA_SAFETY_ON_NULL_RETURN_VAL(key_cmp_cb, NULL);
734 EINA_SAFETY_ON_NULL_RETURN_VAL(key_hash_cb, NULL);
735 EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size <= 2, NULL);
736 EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size >= 17, NULL);
738 new = malloc(sizeof (Eina_Hash));
742 EINA_MAGIC_SET(new, EINA_MAGIC_HASH);
744 new->key_length_cb = key_length_cb;
745 new->key_cmp_cb = key_cmp_cb;
746 new->key_hash_cb = key_hash_cb;
747 new->data_free_cb = data_free_cb;
751 new->size = 1 << buckets_power_size;
752 new->mask = new->size - 1;
757 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
762 eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb)
764 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
765 EINA_KEY_CMP(_eina_string_key_cmp),
766 EINA_KEY_HASH(eina_hash_djb2),
768 EINA_HASH_BUCKET_SIZE);
772 eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb)
774 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
775 EINA_KEY_CMP(_eina_string_key_cmp),
776 EINA_KEY_HASH(eina_hash_superfast),
778 EINA_HASH_BUCKET_SIZE);
782 eina_hash_string_small_new(Eina_Free_Cb data_free_cb)
784 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
785 EINA_KEY_CMP(_eina_string_key_cmp),
786 EINA_KEY_HASH(eina_hash_superfast),
788 EINA_HASH_SMALL_BUCKET_SIZE);
792 eina_hash_int32_new(Eina_Free_Cb data_free_cb)
794 return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
795 EINA_KEY_CMP(_eina_int32_key_cmp),
796 EINA_KEY_HASH(eina_hash_int32),
798 EINA_HASH_BUCKET_SIZE);
802 eina_hash_int64_new(Eina_Free_Cb data_free_cb)
804 return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
805 EINA_KEY_CMP(_eina_int64_key_cmp),
806 EINA_KEY_HASH(eina_hash_int64),
808 EINA_HASH_BUCKET_SIZE);
812 eina_hash_pointer_new(Eina_Free_Cb data_free_cb)
815 return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
816 EINA_KEY_CMP(_eina_int64_key_cmp),
817 EINA_KEY_HASH(eina_hash_int64),
819 EINA_HASH_BUCKET_SIZE);
821 return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
822 EINA_KEY_CMP(_eina_int32_key_cmp),
823 EINA_KEY_HASH(eina_hash_int32),
825 EINA_HASH_BUCKET_SIZE);
830 eina_hash_stringshared_new(Eina_Free_Cb data_free_cb)
832 return eina_hash_new(NULL,
833 EINA_KEY_CMP(_eina_stringshared_key_cmp),
834 EINA_KEY_HASH(eina_hash_superfast),
836 EINA_HASH_BUCKET_SIZE);
840 eina_hash_population(const Eina_Hash *hash)
845 EINA_MAGIC_CHECK_HASH(hash);
846 return hash->population;
850 eina_hash_free(Eina_Hash *hash)
856 EINA_MAGIC_CHECK_HASH(hash);
860 for (i = 0; i < hash->size; i++)
861 eina_rbtree_delete(hash->buckets[i], EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
868 eina_hash_free_buckets(Eina_Hash *hash)
874 EINA_MAGIC_CHECK_HASH(hash);
878 for (i = 0; i < hash->size; i++)
879 eina_rbtree_delete(hash->buckets[i],
880 EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
882 hash->buckets = NULL;
883 hash->population = 0;
888 eina_hash_add_by_hash(Eina_Hash *hash,
894 return eina_hash_add_alloc_by_hash(hash,
903 eina_hash_direct_add_by_hash(Eina_Hash *hash,
909 return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
913 eina_hash_add(Eina_Hash *hash, const void *key, const void *data)
915 unsigned int key_length;
918 EINA_MAGIC_CHECK_HASH(hash);
919 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
920 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
921 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
922 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
924 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
925 key_hash = hash->key_hash_cb(key, key_length);
927 return eina_hash_add_alloc_by_hash(hash, key, key_length, key_length, key_hash, data);
931 eina_hash_direct_add(Eina_Hash *hash, const void *key, const void *data)
936 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
937 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
938 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
939 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
940 EINA_MAGIC_CHECK_HASH(hash);
942 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
943 key_hash = hash->key_hash_cb(key, key_length);
945 return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
949 eina_hash_del_by_key_hash(Eina_Hash *hash,
954 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
955 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
957 return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, NULL);
961 eina_hash_del_by_key(Eina_Hash *hash, const void *key)
963 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
964 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
966 return _eina_hash_del_by_key(hash, key, NULL);
970 eina_hash_del_by_data(Eina_Hash *hash, const void *data)
972 Eina_Hash_Element *hash_element;
973 Eina_Hash_Head *hash_head;
976 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
977 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
978 EINA_MAGIC_CHECK_HASH(hash);
980 hash_element = _eina_hash_find_by_data(hash, data, &key_hash, &hash_head);
984 if (hash_element->tuple.data != data)
987 return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
994 eina_hash_del_by_hash(Eina_Hash *hash,
1002 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1003 EINA_MAGIC_CHECK_HASH(hash);
1006 ret = _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data);
1008 ret = eina_hash_del_by_data(hash, data);
1014 eina_hash_del(Eina_Hash *hash, const void *key, const void *data)
1016 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1017 EINA_MAGIC_CHECK_HASH(hash);
1020 return eina_hash_del_by_data(hash, data);
1022 return _eina_hash_del_by_key(hash, key, data);
1026 eina_hash_find_by_hash(const Eina_Hash *hash,
1031 Eina_Hash_Head *hash_head;
1032 Eina_Hash_Element *hash_element;
1033 Eina_Hash_Tuple tuple;
1038 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1039 EINA_MAGIC_CHECK_HASH(hash);
1042 tuple.key_length = key_length;
1045 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1047 return hash_element->tuple.data;
1053 eina_hash_find(const Eina_Hash *hash, const void *key)
1061 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1062 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1063 EINA_MAGIC_CHECK_HASH(hash);
1065 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
1066 hash_num = hash->key_hash_cb(key, key_length);
1068 return eina_hash_find_by_hash(hash, key, key_length, hash_num);
1072 eina_hash_modify_by_hash(Eina_Hash *hash,
1078 Eina_Hash_Head *hash_head;
1079 Eina_Hash_Element *hash_element;
1080 void *old_data = NULL;
1081 Eina_Hash_Tuple tuple;
1083 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1084 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1085 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
1086 EINA_MAGIC_CHECK_HASH(hash);
1089 tuple.key_length = key_length;
1092 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1095 old_data = hash_element->tuple.data;
1096 hash_element->tuple.data = (void *)data;
1103 eina_hash_set(Eina_Hash *hash, const void *key, const void *data)
1105 Eina_Hash_Tuple tuple;
1106 Eina_Hash_Head *hash_head;
1107 Eina_Hash_Element *hash_element;
1111 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1112 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1113 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1114 EINA_MAGIC_CHECK_HASH(hash);
1116 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
1117 key_hash = hash->key_hash_cb(key, key_length);
1120 tuple.key_length = key_length;
1123 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1126 void *old_data = NULL;
1128 old_data = hash_element->tuple.data;
1132 hash_element->tuple.data = (void *)data;
1136 Eina_Free_Cb cb = hash->data_free_cb;
1137 hash->data_free_cb = NULL;
1138 _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
1139 hash->data_free_cb = cb;
1145 if (!data) return NULL;
1147 eina_hash_add_alloc_by_hash(hash,
1157 eina_hash_modify(Eina_Hash *hash, const void *key, const void *data)
1162 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1163 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1164 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1165 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
1166 EINA_MAGIC_CHECK_HASH(hash);
1168 key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
1169 hash_num = hash->key_hash_cb(key, key_length);
1171 return eina_hash_modify_by_hash(hash, key, key_length, hash_num, data);
1175 eina_hash_move(Eina_Hash *hash, const void *old_key, const void *new_key)
1177 Eina_Free_Cb hash_free_cb;
1179 Eina_Bool result = EINA_FALSE;
1181 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1182 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
1183 EINA_SAFETY_ON_NULL_RETURN_VAL(old_key, EINA_FALSE);
1184 EINA_SAFETY_ON_NULL_RETURN_VAL(new_key, EINA_FALSE);
1185 EINA_MAGIC_CHECK_HASH(hash);
1187 data = eina_hash_find(hash, old_key);
1188 if (!data) goto error;
1190 hash_free_cb = hash->data_free_cb;
1191 hash->data_free_cb = NULL;
1193 eina_hash_del(hash, old_key, data);
1194 result = eina_hash_add(hash, new_key, data);
1196 hash->data_free_cb = hash_free_cb;
1202 /*============================================================================*
1204 *============================================================================*/
1207 eina_hash_foreach(const Eina_Hash *hash,
1208 Eina_Hash_Foreach func,
1212 Eina_Hash_Foreach_Data foreach;
1214 EINA_MAGIC_CHECK_HASH(hash);
1215 EINA_SAFETY_ON_NULL_RETURN(hash);
1216 EINA_SAFETY_ON_NULL_RETURN(func);
1219 foreach.fdata = fdata;
1221 it = eina_hash_iterator_tuple_new(hash);
1224 eina_iterator_foreach(it, EINA_EACH_CB(_eina_foreach_cb), &foreach);
1226 eina_iterator_free(it);
1229 EAPI Eina_Iterator *
1230 eina_hash_iterator_data_new(const Eina_Hash *hash)
1232 Eina_Iterator_Hash *it;
1234 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1235 EINA_MAGIC_CHECK_HASH(hash);
1238 it = calloc(1, sizeof (Eina_Iterator_Hash));
1241 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1246 it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_data_get_content);
1248 it->iterator.version = EINA_ITERATOR_VERSION;
1249 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1250 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1251 _eina_hash_iterator_get_container);
1252 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1254 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1255 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1257 return &it->iterator;
1260 EAPI Eina_Iterator *
1261 eina_hash_iterator_key_new(const Eina_Hash *hash)
1263 Eina_Iterator_Hash *it;
1265 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1266 EINA_MAGIC_CHECK_HASH(hash);
1269 it = calloc(1, sizeof (Eina_Iterator_Hash));
1272 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1277 it->get_content = FUNC_ITERATOR_GET_CONTENT(
1278 _eina_hash_iterator_key_get_content);
1280 it->iterator.version = EINA_ITERATOR_VERSION;
1281 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1282 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1283 _eina_hash_iterator_get_container);
1284 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1286 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1287 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1289 return &it->iterator;
1292 EAPI Eina_Iterator *
1293 eina_hash_iterator_tuple_new(const Eina_Hash *hash)
1295 Eina_Iterator_Hash *it;
1297 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1298 EINA_MAGIC_CHECK_HASH(hash);
1301 it = calloc(1, sizeof (Eina_Iterator_Hash));
1304 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1309 it->get_content = FUNC_ITERATOR_GET_CONTENT(
1310 _eina_hash_iterator_tuple_get_content);
1312 it->iterator.version = EINA_ITERATOR_VERSION;
1313 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1314 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1315 _eina_hash_iterator_get_container);
1316 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1318 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1319 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1321 return &it->iterator;
1324 /* Common hash functions */
1326 /* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
1327 used by WebCore (http://webkit.org/blog/8/hashtables-part-2/) */
1329 eina_hash_superfast(const char *key, int len)
1331 int hash = len, tmp;
1338 for (; len > 0; len--)
1340 hash += get16bits(key);
1341 tmp = (get16bits(key + 2) << 11) ^ hash;
1342 hash = (hash << 16) ^ tmp;
1343 key += 2 * sizeof (uint16_t);
1347 /* Handle end cases */
1351 hash += get16bits(key);
1353 hash ^= key[sizeof (uint16_t)] << 18;
1358 hash += get16bits(key);
1369 /* Force "avalanching" of final 127 bits */