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/>.
29 #include "eina_config.h"
30 #include "eina_private.h"
31 #include "eina_rbtree.h"
33 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
34 #include "eina_safety_checks.h"
35 #include "eina_hash.h"
36 #include "eina_list.h"
38 /*============================================================================*
40 *============================================================================*/
46 #define EINA_MAGIC_CHECK_HASH(d) \
48 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH)) { \
49 EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH); } \
52 #define EINA_MAGIC_CHECK_HASH_ITERATOR(d, ...) \
54 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH_ITERATOR)) \
56 EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH_ITERATOR); \
61 #define EINA_HASH_BUCKET_SIZE 8
62 #define EINA_HASH_SMALL_BUCKET_SIZE 5
64 #define EINA_HASH_RBTREE_MASK 0xFFFF
66 typedef struct _Eina_Hash_Head Eina_Hash_Head;
67 typedef struct _Eina_Hash_Element Eina_Hash_Element;
68 typedef struct _Eina_Hash_Foreach_Data Eina_Hash_Foreach_Data;
69 typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash;
70 typedef struct _Eina_Hash_Each Eina_Hash_Each;
74 Eina_Key_Length key_length_cb;
75 Eina_Key_Cmp key_cmp_cb;
76 Eina_Key_Hash key_hash_cb;
77 Eina_Free_Cb data_free_cb;
79 Eina_Rbtree **buckets;
85 int buckets_power_size;
90 struct _Eina_Hash_Head
99 struct _Eina_Hash_Element
102 Eina_Hash_Tuple tuple;
105 struct _Eina_Hash_Foreach_Data
107 Eina_Hash_Foreach cb;
111 typedef void *(*Eina_Iterator_Get_Content_Callback)(Eina_Iterator_Hash *it);
112 #define FUNC_ITERATOR_GET_CONTENT(Function) \
113 ((Eina_Iterator_Get_Content_Callback)Function)
115 struct _Eina_Iterator_Hash
117 Eina_Iterator iterator;
119 Eina_Iterator_Get_Content_Callback get_content;
120 const Eina_Hash *hash;
122 Eina_Iterator *current;
124 Eina_Hash_Head *hash_head;
125 Eina_Hash_Element *hash_element;
133 struct _Eina_Hash_Each
135 Eina_Hash_Head *hash_head;
136 const Eina_Hash_Element *hash_element;
141 #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
142 || defined (__BORLANDC__) || defined (__TURBOC__)
143 # define get16bits(d) (*((const uint16_t *)(d)))
146 #if !defined (get16bits)
147 # define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
148 + (uint32_t)(((const uint8_t *)(d))[0]))
152 _eina_hash_hash_rbtree_cmp_hash(const Eina_Hash_Head *hash_head,
154 EINA_UNUSED int key_length,
155 EINA_UNUSED void *data)
157 return hash_head->hash - *hash;
160 static Eina_Rbtree_Direction
161 _eina_hash_hash_rbtree_cmp_node(const Eina_Hash_Head *left,
162 const Eina_Hash_Head *right,
163 EINA_UNUSED void *data)
165 if (left->hash - right->hash < 0)
166 return EINA_RBTREE_LEFT;
168 return EINA_RBTREE_RIGHT;
172 _eina_hash_key_rbtree_cmp_key_data(const Eina_Hash_Element *hash_element,
173 const Eina_Hash_Tuple *tuple,
174 EINA_UNUSED unsigned int key_length,
179 result = cmp(hash_element->tuple.key,
180 hash_element->tuple.key_length,
184 if (result == 0 && tuple->data && tuple->data != hash_element->tuple.data)
190 static Eina_Rbtree_Direction
191 _eina_hash_key_rbtree_cmp_node(const Eina_Hash_Element *left,
192 const Eina_Hash_Element *right,
197 result = cmp(left->tuple.key, left->tuple.key_length,
198 right->tuple.key, right->tuple.key_length);
201 return EINA_RBTREE_LEFT;
203 return EINA_RBTREE_RIGHT;
206 static inline Eina_Bool
207 eina_hash_add_alloc_by_hash(Eina_Hash *hash,
208 const void *key, int key_length, int alloc_length,
212 Eina_Hash_Element *new_hash_element = NULL;
213 Eina_Hash_Head *hash_head;
216 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
217 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
218 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
219 EINA_MAGIC_CHECK_HASH(hash);
221 /* Apply eina mask to hash. */
222 hash_num = key_hash & hash->mask;
223 key_hash >>= hash->buckets_power_size;
224 key_hash &= EINA_HASH_RBTREE_MASK;
228 hash->buckets = calloc(sizeof (Eina_Rbtree *), hash->size);
229 if (!hash->buckets) goto on_error;
234 /* Look up for head node. */
235 hash_head = (Eina_Hash_Head *)
236 eina_rbtree_inline_lookup(hash->buckets[hash_num],
238 EINA_RBTREE_CMP_KEY_CB(
239 _eina_hash_hash_rbtree_cmp_hash),
244 /* If not found allocate it and an element. */
245 hash_head = malloc(sizeof(Eina_Hash_Head));
249 hash_head->hash = key_hash;
250 hash_head->head = NULL;
252 hash->buckets[hash_num] =
253 eina_rbtree_inline_insert(hash->buckets[hash_num],
254 EINA_RBTREE_GET(hash_head),
255 EINA_RBTREE_CMP_NODE_CB(
256 _eina_hash_hash_rbtree_cmp_node),
262 (No more lookup as we expect to support more than one item for one key).
264 new_hash_element = malloc(sizeof (Eina_Hash_Element) + alloc_length);
265 if (!new_hash_element)
268 /* Setup the element */
269 new_hash_element->tuple.key_length = key_length;
270 new_hash_element->tuple.data = (void *)data;
271 if (alloc_length > 0)
273 new_hash_element->tuple.key = (char *)(new_hash_element + 1);
274 memcpy((char *)new_hash_element->tuple.key, key, alloc_length);
277 new_hash_element->tuple.key = key;
279 /* add the new element to the hash. */
280 hash_head->head = eina_rbtree_inline_insert(hash_head->head,
281 EINA_RBTREE_GET(new_hash_element),
282 EINA_RBTREE_CMP_NODE_CB(
283 _eina_hash_key_rbtree_cmp_node),
284 (const void *)hash->key_cmp_cb);
293 _eina_hash_rbtree_each(EINA_UNUSED const Eina_Rbtree *container,
294 const Eina_Hash_Head *hash_head,
295 Eina_Hash_Each *data)
298 Eina_Hash_Element *hash_element;
299 Eina_Bool found = EINA_TRUE;
301 it = eina_rbtree_iterator_prefix(hash_head->head);
302 EINA_ITERATOR_FOREACH(it, hash_element)
304 if (hash_element->tuple.data == data->data)
306 data->hash_element = hash_element;
307 data->hash_head = (Eina_Hash_Head *)hash_head;
313 eina_iterator_free(it);
317 static inline Eina_Hash_Element *
318 _eina_hash_find_by_hash(const Eina_Hash *hash,
319 Eina_Hash_Tuple *tuple,
321 Eina_Hash_Head **hash_head)
323 Eina_Hash_Element *hash_element;
324 int rb_hash = (key_hash >> hash->buckets_power_size)
325 & EINA_HASH_RBTREE_MASK;
327 key_hash &= hash->mask;
332 *hash_head = (Eina_Hash_Head *)
333 eina_rbtree_inline_lookup(hash->buckets[key_hash],
335 EINA_RBTREE_CMP_KEY_CB(
336 _eina_hash_hash_rbtree_cmp_hash),
341 hash_element = (Eina_Hash_Element *)
342 eina_rbtree_inline_lookup((*hash_head)->head,
344 EINA_RBTREE_CMP_KEY_CB(
345 _eina_hash_key_rbtree_cmp_key_data),
346 (const void *)hash->key_cmp_cb);
351 static inline Eina_Hash_Element *
352 _eina_hash_find_by_data(const Eina_Hash *hash,
355 Eina_Hash_Head **hash_head)
364 each.hash_element = NULL;
367 for (hash_num = 0; hash_num < hash->size; hash_num++)
369 if (!hash->buckets[hash_num])
372 it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]);
373 eina_iterator_foreach(it, EINA_EACH_CB(_eina_hash_rbtree_each), &each);
374 eina_iterator_free(it);
376 if (each.hash_element)
378 *key_hash = hash_num;
379 *hash_head = each.hash_head;
380 return (Eina_Hash_Element *)each.hash_element;
388 _eina_hash_el_free(Eina_Hash_Element *hash_element, Eina_Hash *hash)
390 if (hash->data_free_cb)
391 hash->data_free_cb(hash_element->tuple.data);
397 _eina_hash_head_free(Eina_Hash_Head *hash_head, Eina_Hash *hash)
399 eina_rbtree_delete(hash_head->head, EINA_RBTREE_FREE_CB(_eina_hash_el_free), hash);
404 _eina_hash_del_by_hash_el(Eina_Hash *hash,
405 Eina_Hash_Element *hash_element,
406 Eina_Hash_Head *hash_head,
409 hash_head->head = eina_rbtree_inline_remove(hash_head->head, EINA_RBTREE_GET(
410 hash_element), EINA_RBTREE_CMP_NODE_CB(
411 _eina_hash_key_rbtree_cmp_node),
412 (const void *)hash->key_cmp_cb);
414 if (!hash_head->head)
416 key_hash &= hash->mask;
418 hash->buckets[key_hash] =
419 eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET(
421 EINA_RBTREE_CMP_NODE_CB(
422 _eina_hash_hash_rbtree_cmp_node), NULL);
427 if (hash->population == 0)
430 hash->buckets = NULL;
433 _eina_hash_el_free(hash_element, hash);
439 _eina_hash_del_by_key_hash(Eina_Hash *hash,
445 Eina_Hash_Element *hash_element;
446 Eina_Hash_Head *hash_head;
447 Eina_Hash_Tuple tuple;
449 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
450 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
451 EINA_MAGIC_CHECK_HASH(hash);
456 tuple.key = (void *)key;
457 tuple.key_length = key_length;
458 tuple.data = (void *)data;
460 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
464 return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
468 _eina_hash_compute(const Eina_Hash *hash, const void *key, int *key_length, int *key_hash)
470 *key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0;
471 *key_hash = hash->key_hash_cb(key, *key_length);
475 _eina_hash_del_by_key(Eina_Hash *hash, const void *key, const void *data)
477 int key_length, key_hash;
479 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
480 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
481 EINA_MAGIC_CHECK_HASH(hash);
486 _eina_hash_compute(hash, key, &key_length, &key_hash);
487 return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data);
491 _eina_stringshared_hash(const void *key, int key_length EINA_UNUSED)
493 return eina_hash_superfast((const void*) &key, sizeof (void*));
497 _eina_string_key_length(const char *key)
502 return (int)strlen(key) + 1;
506 _eina_string_key_cmp(const char *key1, int key1_length,
507 const char *key2, int key2_length)
511 delta = key1_length - key2_length;
512 if (delta) return delta;
513 return strcmp(key1, key2);
517 _eina_stringshared_key_cmp(const char *key1, EINA_UNUSED int key1_length,
518 const char *key2, EINA_UNUSED int key2_length)
520 // logically we want to do this:
521 // return key1 - key2;
522 // but since they are ptrs and an int can't store the different of 2 ptrs in
523 // either 32 or 64bit (signed hasn't got enough range for the diff of 2
524 // 32bit values regardless of their type... we'd need 33bits or 65bits)
526 if (key1 == key2) return 0;
527 if (key1 > key2) return 1;
529 // NOTE: this seems odd. we don't sort by string content at all... we sort
530 // by pointer location in memory. this seems odd at first, BUT this does
531 // work because with stringshare each ptr holds a unique string and we
532 // cannot have 2 ptrs in stringshare have the same string content thus we
533 // can't go wrong and have 2 ptrs be different yet the string key be the
534 // same, thus we can avoid walking the string, so sorting by ptr value is
535 // frankly as good as anything. :) (this is only within the bucket too)
539 _eina_int32_key_length(EINA_UNUSED const uint32_t *key)
545 _eina_int32_key_cmp(const uint32_t *key1, EINA_UNUSED int key1_length,
546 const uint32_t *key2, EINA_UNUSED int key2_length)
548 if (*key1 == *key2) return 0;
549 if (*key1 > *key2) return 1;
554 _eina_int64_key_length(EINA_UNUSED const uint64_t *key)
556 return sizeof(int64_t);
560 _eina_int64_key_cmp(const uint64_t *key1, EINA_UNUSED int key1_length,
561 const uint64_t *key2, EINA_UNUSED int key2_length)
563 if (*key1 == *key2) return 0;
564 if (*key1 > *key2) return 1;
569 _eina_foreach_cb(const Eina_Hash *hash,
570 Eina_Hash_Tuple *data,
571 Eina_Hash_Foreach_Data *fdata)
573 return fdata->cb((Eina_Hash *)hash,
576 (void *)fdata->fdata);
580 _eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it)
582 Eina_Hash_Element *stuff;
584 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
586 stuff = it->hash_element;
591 return stuff->tuple.data;
595 _eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it)
597 Eina_Hash_Element *stuff;
599 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
601 stuff = it->hash_element;
606 return (void *)stuff->tuple.key;
609 static Eina_Hash_Tuple *
610 _eina_hash_iterator_tuple_get_content(Eina_Iterator_Hash *it)
612 Eina_Hash_Element *stuff;
614 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
616 stuff = it->hash_element;
621 return &stuff->tuple;
625 _eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data)
630 if (!(it->index < it->hash->population))
641 ok = eina_iterator_next(it->list, (void **)(void *)&it->hash_element);
644 eina_iterator_free(it->list);
647 ok = eina_iterator_next(it->current, (void **)(void *)&it->hash_head);
650 eina_iterator_free(it->current);
656 it->list = eina_rbtree_iterator_prefix(it->hash_head->head);
657 ok = eina_iterator_next(it->list, (void **)(void *)&it->hash_element);
664 if (ok == EINA_FALSE)
666 while (bucket < it->hash->size)
668 if (it->hash->buckets[bucket])
671 eina_rbtree_iterator_prefix(it->hash->buckets[bucket]);
672 ok = eina_iterator_next(it->current, (void **)(void *)&it->hash_head);
676 eina_iterator_free(it->current);
683 eina_iterator_free(it->list);
685 it->list = eina_rbtree_iterator_prefix(it->hash_head->head);
686 ok = eina_iterator_next(it->list, (void **)(void *)&it->hash_element);
687 if (bucket == it->hash->size)
695 *data = it->get_content(it);
701 _eina_hash_iterator_get_container(Eina_Iterator_Hash *it)
703 EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL);
704 return (void *)it->hash;
708 _eina_hash_iterator_free(Eina_Iterator_Hash *it)
710 EINA_MAGIC_CHECK_HASH_ITERATOR(it);
712 eina_iterator_free(it->current);
715 eina_iterator_free(it->list);
724 /*============================================================================*
726 *============================================================================*/
728 /*============================================================================*
730 *============================================================================*/
733 eina_hash_free_cb_set(Eina_Hash *hash, Eina_Free_Cb data_free_cb)
735 EINA_MAGIC_CHECK_HASH(hash);
736 EINA_SAFETY_ON_NULL_RETURN(hash);
738 hash->data_free_cb = data_free_cb;
742 eina_hash_new(Eina_Key_Length key_length_cb,
743 Eina_Key_Cmp key_cmp_cb,
744 Eina_Key_Hash key_hash_cb,
745 Eina_Free_Cb data_free_cb,
746 int buckets_power_size)
748 /* FIXME: Use mempool. */
751 EINA_SAFETY_ON_NULL_RETURN_VAL(key_cmp_cb, NULL);
752 EINA_SAFETY_ON_NULL_RETURN_VAL(key_hash_cb, NULL);
753 EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size <= 2, NULL);
754 EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size >= 17, NULL);
756 new = malloc(sizeof (Eina_Hash));
760 EINA_MAGIC_SET(new, EINA_MAGIC_HASH);
762 new->key_length_cb = key_length_cb;
763 new->key_cmp_cb = key_cmp_cb;
764 new->key_hash_cb = key_hash_cb;
765 new->data_free_cb = data_free_cb;
769 new->size = 1 << buckets_power_size;
770 new->mask = new->size - 1;
771 new->buckets_power_size = buckets_power_size;
780 eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb)
782 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
783 EINA_KEY_CMP(_eina_string_key_cmp),
784 EINA_KEY_HASH(eina_hash_djb2),
786 EINA_HASH_BUCKET_SIZE);
790 eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb)
792 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
793 EINA_KEY_CMP(_eina_string_key_cmp),
794 EINA_KEY_HASH(eina_hash_superfast),
796 EINA_HASH_BUCKET_SIZE);
800 eina_hash_string_small_new(Eina_Free_Cb data_free_cb)
802 return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
803 EINA_KEY_CMP(_eina_string_key_cmp),
804 EINA_KEY_HASH(eina_hash_superfast),
806 EINA_HASH_SMALL_BUCKET_SIZE);
810 eina_hash_int32_new(Eina_Free_Cb data_free_cb)
812 return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
813 EINA_KEY_CMP(_eina_int32_key_cmp),
814 EINA_KEY_HASH(eina_hash_int32),
816 EINA_HASH_BUCKET_SIZE);
820 eina_hash_int64_new(Eina_Free_Cb data_free_cb)
822 return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
823 EINA_KEY_CMP(_eina_int64_key_cmp),
824 EINA_KEY_HASH(eina_hash_int64),
826 EINA_HASH_BUCKET_SIZE);
830 eina_hash_pointer_new(Eina_Free_Cb data_free_cb)
833 return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
834 EINA_KEY_CMP(_eina_int64_key_cmp),
835 EINA_KEY_HASH(eina_hash_int64),
837 EINA_HASH_BUCKET_SIZE);
839 return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
840 EINA_KEY_CMP(_eina_int32_key_cmp),
841 EINA_KEY_HASH(eina_hash_int32),
843 EINA_HASH_BUCKET_SIZE);
848 eina_hash_stringshared_new(Eina_Free_Cb data_free_cb)
850 return eina_hash_new(NULL,
851 EINA_KEY_CMP(_eina_stringshared_key_cmp),
852 EINA_KEY_HASH(_eina_stringshared_hash),
854 EINA_HASH_BUCKET_SIZE);
858 eina_hash_population(const Eina_Hash *hash)
863 EINA_MAGIC_CHECK_HASH(hash);
864 return hash->population;
868 eina_hash_free(Eina_Hash *hash)
874 EINA_MAGIC_CHECK_HASH(hash);
878 for (i = 0; i < hash->size; i++)
879 eina_rbtree_delete(hash->buckets[i], EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
886 eina_hash_free_buckets(Eina_Hash *hash)
892 EINA_MAGIC_CHECK_HASH(hash);
896 for (i = 0; i < hash->size; i++)
897 eina_rbtree_delete(hash->buckets[i],
898 EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
900 hash->buckets = NULL;
901 hash->population = 0;
906 eina_hash_add_by_hash(Eina_Hash *hash,
912 return eina_hash_add_alloc_by_hash(hash,
921 eina_hash_direct_add_by_hash(Eina_Hash *hash,
927 return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
931 eina_hash_add(Eina_Hash *hash, const void *key, const void *data)
936 EINA_MAGIC_CHECK_HASH(hash);
937 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
938 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
939 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
940 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
942 _eina_hash_compute(hash, key, &key_length, &key_hash);
944 return eina_hash_add_alloc_by_hash(hash, key, key_length, key_length, key_hash, data);
948 eina_hash_direct_add(Eina_Hash *hash, const void *key, const void *data)
953 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
954 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
955 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
956 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
957 EINA_MAGIC_CHECK_HASH(hash);
959 _eina_hash_compute(hash, key, &key_length, &key_hash);
961 return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
965 eina_hash_del_by_key_hash(Eina_Hash *hash,
970 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
971 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
973 return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, NULL);
977 eina_hash_del_by_key(Eina_Hash *hash, const void *key)
979 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
980 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
982 return _eina_hash_del_by_key(hash, key, NULL);
986 eina_hash_del_by_data(Eina_Hash *hash, const void *data)
988 Eina_Hash_Element *hash_element;
989 Eina_Hash_Head *hash_head;
992 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
993 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
994 EINA_MAGIC_CHECK_HASH(hash);
996 hash_element = _eina_hash_find_by_data(hash, data, &key_hash, &hash_head);
1000 if (hash_element->tuple.data != data)
1003 return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
1010 eina_hash_del_by_hash(Eina_Hash *hash,
1018 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1019 EINA_MAGIC_CHECK_HASH(hash);
1022 ret = _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data);
1024 ret = eina_hash_del_by_data(hash, data);
1030 eina_hash_del(Eina_Hash *hash, const void *key, const void *data)
1032 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1033 EINA_MAGIC_CHECK_HASH(hash);
1036 return eina_hash_del_by_data(hash, data);
1038 return _eina_hash_del_by_key(hash, key, data);
1042 eina_hash_find_by_hash(const Eina_Hash *hash,
1047 Eina_Hash_Head *hash_head;
1048 Eina_Hash_Element *hash_element;
1049 Eina_Hash_Tuple tuple;
1054 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1055 EINA_MAGIC_CHECK_HASH(hash);
1058 tuple.key_length = key_length;
1061 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1063 return hash_element->tuple.data;
1069 eina_hash_find(const Eina_Hash *hash, const void *key)
1077 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1078 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1079 EINA_MAGIC_CHECK_HASH(hash);
1081 if (hash->population == 0)
1084 _eina_hash_compute(hash, key, &key_length, &key_hash);
1086 return eina_hash_find_by_hash(hash, key, key_length, key_hash);
1090 eina_hash_modify_by_hash(Eina_Hash *hash,
1096 Eina_Hash_Head *hash_head;
1097 Eina_Hash_Element *hash_element;
1098 void *old_data = NULL;
1099 Eina_Hash_Tuple tuple;
1101 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1102 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1103 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
1104 EINA_MAGIC_CHECK_HASH(hash);
1107 tuple.key_length = key_length;
1110 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1113 old_data = hash_element->tuple.data;
1114 hash_element->tuple.data = (void *)data;
1121 eina_hash_set(Eina_Hash *hash, const void *key, const void *data)
1123 Eina_Hash_Tuple tuple;
1124 Eina_Hash_Head *hash_head;
1125 Eina_Hash_Element *hash_element;
1129 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1130 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1131 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1132 EINA_MAGIC_CHECK_HASH(hash);
1134 _eina_hash_compute(hash, key, &key_length, &key_hash);
1137 tuple.key_length = key_length;
1140 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1143 void *old_data = NULL;
1145 old_data = hash_element->tuple.data;
1149 hash_element->tuple.data = (void *)data;
1153 Eina_Free_Cb cb = hash->data_free_cb;
1154 hash->data_free_cb = NULL;
1155 _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);
1156 hash->data_free_cb = cb;
1162 if (!data) return NULL;
1164 eina_hash_add_alloc_by_hash(hash,
1174 eina_hash_modify(Eina_Hash *hash, const void *key, const void *data)
1179 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL);
1180 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL);
1181 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
1182 EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
1183 EINA_MAGIC_CHECK_HASH(hash);
1185 _eina_hash_compute(hash, key, &key_length, &key_hash);
1187 return eina_hash_modify_by_hash(hash, key, key_length, key_hash, data);
1191 eina_hash_move(Eina_Hash *hash, const void *old_key, const void *new_key)
1193 Eina_Free_Cb hash_free_cb;
1195 Eina_Bool result = EINA_FALSE;
1197 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
1198 EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE);
1199 EINA_SAFETY_ON_NULL_RETURN_VAL(old_key, EINA_FALSE);
1200 EINA_SAFETY_ON_NULL_RETURN_VAL(new_key, EINA_FALSE);
1201 EINA_MAGIC_CHECK_HASH(hash);
1203 data = eina_hash_find(hash, old_key);
1204 if (!data) goto error;
1206 hash_free_cb = hash->data_free_cb;
1207 hash->data_free_cb = NULL;
1209 eina_hash_del(hash, old_key, data);
1210 result = eina_hash_add(hash, new_key, data);
1212 hash->data_free_cb = hash_free_cb;
1218 /*============================================================================*
1220 *============================================================================*/
1223 eina_hash_foreach(const Eina_Hash *hash,
1224 Eina_Hash_Foreach func,
1228 Eina_Hash_Foreach_Data foreach;
1230 EINA_MAGIC_CHECK_HASH(hash);
1231 EINA_SAFETY_ON_NULL_RETURN(hash);
1232 EINA_SAFETY_ON_NULL_RETURN(func);
1235 foreach.fdata = fdata;
1237 it = eina_hash_iterator_tuple_new(hash);
1240 eina_iterator_foreach(it, EINA_EACH_CB(_eina_foreach_cb), &foreach);
1242 eina_iterator_free(it);
1245 EAPI Eina_Iterator *
1246 eina_hash_iterator_data_new(const Eina_Hash *hash)
1248 Eina_Iterator_Hash *it;
1250 if (!hash) return NULL;
1251 EINA_MAGIC_CHECK_HASH(hash);
1253 it = calloc(1, sizeof (Eina_Iterator_Hash));
1254 if (!it) return NULL;
1257 it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_data_get_content);
1259 it->iterator.version = EINA_ITERATOR_VERSION;
1260 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1261 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1262 _eina_hash_iterator_get_container);
1263 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1265 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1266 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1268 return &it->iterator;
1271 EAPI Eina_Iterator *
1272 eina_hash_iterator_key_new(const Eina_Hash *hash)
1274 Eina_Iterator_Hash *it;
1276 if (!hash) return NULL;
1277 EINA_MAGIC_CHECK_HASH(hash);
1279 it = calloc(1, sizeof (Eina_Iterator_Hash));
1280 if (!it) return NULL;
1283 it->get_content = FUNC_ITERATOR_GET_CONTENT(
1284 _eina_hash_iterator_key_get_content);
1286 it->iterator.version = EINA_ITERATOR_VERSION;
1287 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1288 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1289 _eina_hash_iterator_get_container);
1290 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1292 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1293 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1295 return &it->iterator;
1298 EAPI Eina_Iterator *
1299 eina_hash_iterator_tuple_new(const Eina_Hash *hash)
1301 Eina_Iterator_Hash *it;
1303 if (!hash) return NULL;
1304 EINA_MAGIC_CHECK_HASH(hash);
1306 it = calloc(1, sizeof (Eina_Iterator_Hash));
1307 if (!it) return NULL;
1310 it->get_content = FUNC_ITERATOR_GET_CONTENT(
1311 _eina_hash_iterator_tuple_get_content);
1313 it->iterator.version = EINA_ITERATOR_VERSION;
1314 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
1315 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1316 _eina_hash_iterator_get_container);
1317 it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
1319 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1320 EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR);
1322 return &it->iterator;
1325 /* Common hash functions */
1327 /* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
1328 used by WebCore (http://webkit.org/blog/8/hashtables-part-2/) */
1330 eina_hash_superfast(const char *key, int len)
1332 int hash = len, tmp;
1339 for (; len > 0; len--)
1341 hash += get16bits(key);
1342 tmp = (get16bits(key + 2) << 11) ^ hash;
1343 hash = (hash << 16) ^ tmp;
1344 key += 2 * sizeof (uint16_t);
1348 /* Handle end cases */
1352 hash += get16bits(key);
1354 hash ^= key[sizeof (uint16_t)] << 18;
1359 hash += get16bits(key);
1370 /* Force "avalanching" of final 127 bits */
1382 eina_hash_list_append(Eina_Hash *hash, const void *key, const void *data)
1384 Eina_Hash_Tuple tuple;
1385 Eina_Hash_Head *hash_head;
1386 Eina_Hash_Element *hash_element;
1390 EINA_SAFETY_ON_NULL_RETURN(hash);
1391 EINA_SAFETY_ON_NULL_RETURN(hash->key_hash_cb);
1392 EINA_SAFETY_ON_NULL_RETURN(key);
1393 EINA_SAFETY_ON_NULL_RETURN(data);
1394 EINA_MAGIC_CHECK_HASH(hash);
1396 _eina_hash_compute(hash, key, &key_length, &key_hash);
1399 tuple.key_length = key_length;
1402 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1404 hash_element->tuple.data = eina_list_append(hash_element->tuple.data, data);
1406 eina_hash_add_alloc_by_hash(hash,
1411 eina_list_append(NULL, data));
1415 eina_hash_list_direct_append(Eina_Hash *hash, const void *key, const void *data)
1417 Eina_Hash_Tuple tuple;
1418 Eina_Hash_Head *hash_head;
1419 Eina_Hash_Element *hash_element;
1423 EINA_SAFETY_ON_NULL_RETURN(hash);
1424 EINA_SAFETY_ON_NULL_RETURN(hash->key_hash_cb);
1425 EINA_SAFETY_ON_NULL_RETURN(key);
1426 EINA_SAFETY_ON_NULL_RETURN(data);
1427 EINA_MAGIC_CHECK_HASH(hash);
1429 _eina_hash_compute(hash, key, &key_length, &key_hash);
1432 tuple.key_length = key_length;
1435 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1437 hash_element->tuple.data = eina_list_append(hash_element->tuple.data, data);
1439 eina_hash_add_alloc_by_hash(hash,
1444 eina_list_append(NULL, data));
1448 eina_hash_list_prepend(Eina_Hash *hash, const void *key, const void *data)
1450 Eina_Hash_Tuple tuple;
1451 Eina_Hash_Head *hash_head;
1452 Eina_Hash_Element *hash_element;
1456 EINA_SAFETY_ON_NULL_RETURN(hash);
1457 EINA_SAFETY_ON_NULL_RETURN(hash->key_hash_cb);
1458 EINA_SAFETY_ON_NULL_RETURN(key);
1459 EINA_SAFETY_ON_NULL_RETURN(data);
1460 EINA_MAGIC_CHECK_HASH(hash);
1462 _eina_hash_compute(hash, key, &key_length, &key_hash);
1465 tuple.key_length = key_length;
1468 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1470 hash_element->tuple.data = eina_list_prepend(hash_element->tuple.data, data);
1472 eina_hash_add_alloc_by_hash(hash,
1477 eina_list_append(NULL, data));
1481 eina_hash_list_direct_prepend(Eina_Hash *hash, const void *key, const void *data)
1483 Eina_Hash_Tuple tuple;
1484 Eina_Hash_Head *hash_head;
1485 Eina_Hash_Element *hash_element;
1489 EINA_SAFETY_ON_NULL_RETURN(hash);
1490 EINA_SAFETY_ON_NULL_RETURN(hash->key_hash_cb);
1491 EINA_SAFETY_ON_NULL_RETURN(key);
1492 EINA_SAFETY_ON_NULL_RETURN(data);
1493 EINA_MAGIC_CHECK_HASH(hash);
1495 _eina_hash_compute(hash, key, &key_length, &key_hash);
1498 tuple.key_length = key_length;
1501 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1503 hash_element->tuple.data = eina_list_prepend(hash_element->tuple.data, data);
1505 eina_hash_add_alloc_by_hash(hash,
1510 eina_list_append(NULL, data));
1514 eina_hash_list_remove(Eina_Hash *hash, const void *key, const void *data)
1516 Eina_Hash_Tuple tuple;
1517 Eina_Hash_Head *hash_head;
1518 Eina_Hash_Element *hash_element;
1522 EINA_SAFETY_ON_NULL_RETURN(hash);
1523 EINA_SAFETY_ON_NULL_RETURN(hash->key_hash_cb);
1524 EINA_SAFETY_ON_NULL_RETURN(key);
1525 EINA_SAFETY_ON_NULL_RETURN(data);
1526 EINA_MAGIC_CHECK_HASH(hash);
1528 _eina_hash_compute(hash, key, &key_length, &key_hash);
1531 tuple.key_length = key_length;
1534 hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head);
1535 if (!hash_element) return;
1536 hash_element->tuple.data = eina_list_remove(hash_element->tuple.data, data);
1537 if (!hash_element->tuple.data)
1538 _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash);