EAPI Eina_Hash * eina_hash_new(Eina_Key_Length key_length_cb,
Eina_Key_Cmp key_cmp_cb,
Eina_Key_Hash key_hash_cb,
- Eina_Free_Cb data_free_cb);
+ Eina_Free_Cb data_free_cb,
+ int buckets_power_size);
EAPI Eina_Hash * eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb);
EAPI Eina_Hash * eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb);
+EAPI Eina_Hash * eina_hash_string_small_new(Eina_Free_Cb data_free_cb);
EAPI Eina_Hash * eina_hash_int32_new(Eina_Free_Cb data_free_cb);
EAPI Eina_Hash * eina_hash_int64_new(Eina_Free_Cb data_free_cb);
EAPI Eina_Hash * eina_hash_pointer_new(Eina_Free_Cb data_free_cb);
static inline int eina_hash_djb2(const char *key, int len);
/* Hash function from http://www.concentric.net/~Ttwang/tech/inthash.htm */
-static inline int eina_hash_int32(unsigned int *pkey, __UNUSED__ int len);
-static inline int eina_hash_int64(unsigned long int *pkey, __UNUSED__ int len);
+static inline int eina_hash_int32(unsigned int *pkey, int len);
+static inline int eina_hash_int64(unsigned long int *pkey, int len);
#include "eina_inline_hash.x"
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_BUCKET_SIZE 8
+#define EINA_HASH_SMALL_BUCKET_SIZE 5
+
#define EINA_HASH_RBTREE_MASK 0xFFF
typedef struct _Eina_Hash_Head Eina_Hash_Head;
Eina_Free_Cb data_free_cb;
Eina_Rbtree **buckets;
+ int size;
+ int mask;
+
int population;
EINA_MAGIC;
error = EINA_ERROR_OUT_OF_MEMORY;
/* Apply eina mask to hash. */
- hash_num = key_hash & EINA_HASH_BUCKET_MASK;
+ hash_num = key_hash & hash->mask;
key_hash &= EINA_HASH_RBTREE_MASK;
if (!hash->buckets)
{
- hash->buckets = malloc(sizeof (Eina_Rbtree*) * EINA_HASH_BUCKET_SIZE);
- memset(hash->buckets, 0, sizeof (Eina_Rbtree*) * EINA_HASH_BUCKET_SIZE);
+ hash->buckets = malloc(sizeof (Eina_Rbtree*) * hash->size);
+ memset(hash->buckets, 0, sizeof (Eina_Rbtree*) * hash->size);
eh = NULL;
}
Eina_Hash_El *el;
int rb_hash = key_hash & EINA_HASH_RBTREE_MASK;
- key_hash &= EINA_HASH_BUCKET_MASK;
+ key_hash &= hash->mask;
if (!hash->buckets) return NULL;
each.el = NULL;
each.data = data;
- for (hash_num = 0; hash_num < EINA_HASH_BUCKET_SIZE; hash_num++)
+ for (hash_num = 0; hash_num < hash->size; hash_num++)
{
if (!hash->buckets[hash_num])
continue;
if (!eh->head)
{
- key_hash &= EINA_HASH_BUCKET_MASK;
+ key_hash &= hash->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);
if (ok == EINA_FALSE)
{
- while (bucket < EINA_HASH_BUCKET_SIZE)
+ while (bucket < it->hash->size)
{
if (it->hash->buckets[bucket] != NULL)
{
if (it->list) eina_iterator_free(it->list);
it->list = eina_rbtree_iterator_prefix(it->eh->head);
ok = eina_iterator_next(it->list, (void**) &it->el);
- if (bucket == EINA_HASH_BUCKET_SIZE) ok = EINA_FALSE;
+ if (bucket == it->hash->size) ok = EINA_FALSE;
}
it->index++;
eina_error_shutdown();
return --_eina_hash_init_count;
}
-
EAPI Eina_Hash *
eina_hash_new(Eina_Key_Length key_length_cb,
Eina_Key_Cmp key_cmp_cb,
Eina_Key_Hash key_hash_cb,
- Eina_Free_Cb data_free_cb)
+ Eina_Free_Cb data_free_cb,
+ int buckets_power_size)
{
/* FIXME: Use mempool. */
Eina_Hash *new;
eina_error_set(0);
if (!key_length_cb || !key_cmp_cb) return NULL;
+ if (buckets_power_size < 3 || buckets_power_size > 16) return NULL;
new = malloc(sizeof (Eina_Hash));
if (!new) goto on_error;
new->buckets = NULL;
new->population = 0;
+ new->size = 1 << buckets_power_size;
+ new->mask = new->size - 1;
+
EINA_MAGIC_SET(new, EINA_MAGIC_HASH);
return new;
return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
EINA_KEY_CMP(_eina_string_key_cmp),
EINA_KEY_HASH(eina_hash_djb2),
- data_free_cb);
+ data_free_cb,
+ EINA_HASH_BUCKET_SIZE);
}
EAPI Eina_Hash *
return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
EINA_KEY_CMP(_eina_string_key_cmp),
EINA_KEY_HASH(eina_hash_superfast),
- data_free_cb);
+ data_free_cb,
+ EINA_HASH_BUCKET_SIZE);
+}
+
+EAPI Eina_Hash *
+eina_hash_string_small_new(Eina_Free_Cb data_free_cb)
+{
+ return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
+ EINA_KEY_CMP(_eina_string_key_cmp),
+ EINA_KEY_HASH(eina_hash_superfast),
+ data_free_cb,
+ EINA_HASH_SMALL_BUCKET_SIZE);
}
EAPI Eina_Hash *
return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
EINA_KEY_CMP(_eina_int32_key_cmp),
EINA_KEY_HASH(eina_hash_int32),
- data_free_cb);
+ data_free_cb,
+ EINA_HASH_BUCKET_SIZE);
}
EAPI Eina_Hash *
return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
EINA_KEY_CMP(_eina_int64_key_cmp),
EINA_KEY_HASH(eina_hash_int64),
- data_free_cb);
+ data_free_cb,
+ EINA_HASH_BUCKET_SIZE);
}
EAPI Eina_Hash *
return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length),
EINA_KEY_CMP(_eina_int64_key_cmp),
EINA_KEY_HASH(eina_hash_int64),
- data_free_cb);
+ data_free_cb,
+ EINA_HASH_BUCKET_SIZE);
#else
return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length),
EINA_KEY_CMP(_eina_int32_key_cmp),
EINA_KEY_HASH(eina_hash_int32),
- data_free_cb);
+ data_free_cb,
+ EINA_HASH_BUCKET_SIZE);
#endif
}
if (!hash) return;
if (hash->buckets)
- for (i = 0; i < EINA_HASH_BUCKET_SIZE; i++)
+ for (i = 0; i < hash->size; i++)
eina_rbtree_delete(hash->buckets[i], EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
free(hash);
}