2 * Author: Humberto Naves (hsnaves@gmail.com)
15 #define INDEX_FOR(hash, size) ((hash) & ((size) - 1))
23 typedef struct _entry
*entry
;
26 struct _hashpool
*const pool
;
27 unsigned int tablelength
;
28 unsigned int entrycount
;
29 unsigned int loadlimit
;
30 struct _entry
**table
;
41 hashpool
hashpool_create (size_t numtables
, size_t numentries
)
43 hashpool pool
= (hashpool
) xmalloc (sizeof (struct _hashpool
));
44 pool
->tablepool
= fixedpool_create (sizeof (struct _hashtable
), numtables
, 0);
45 pool
->entrypool
= fixedpool_create (sizeof (struct _entry
), numentries
, 0);
50 void destroy_hashtable (void *ptr
, void *arg
)
59 void hashpool_destroy (hashpool pool
)
61 fixedpool_destroy (pool
->tablepool
, &destroy_hashtable
, NULL
);
62 fixedpool_destroy (pool
->entrypool
, NULL
, NULL
);
67 entry
alloc_entry (hashpool pool
)
69 return fixedpool_alloc (pool
->entrypool
);
73 void free_entry (hashpool pool
, entry e
)
75 fixedpool_free (pool
->entrypool
, e
);
79 hashtable
hashtable_alloc (hashpool pool
, unsigned int size
, hashfn hashfn
, hashequalsfn eqfn
)
84 ht
= fixedpool_alloc (pool
->tablepool
);
85 ht
->table
= (entry
*) xmalloc (sizeof (entry
) * size
);
86 memset (ht
->table
, 0, size
* sizeof (entry
));
88 ptr
= (hashpool
*) &ht
->pool
;
91 ht
->tablelength
= size
;
95 ht
->loadlimit
= size
>> 1;
100 void hashtable_free (hashtable ht
, hashtraversefn destroyfn
, void *arg
)
105 for (i
= 0; i
< ht
->tablelength
; i
++) {
106 for (e
= ht
->table
[i
]; e
; e
= e
->next
) {
108 destroyfn (e
->key
, e
->value
, e
->hash
, arg
);
109 fixedpool_free (ht
->pool
->entrypool
, e
);
113 fixedpool_grow (ht
->pool
->entrypool
, ht
->table
, ht
->tablelength
);
118 fixedpool_free (ht
->pool
->tablepool
, ht
);
122 void hashtable_grow (hashtable ht
)
126 unsigned int newsize
, i
, index
;
128 newsize
= ht
->tablelength
<< 1;
130 newtable
= (entry
*) xmalloc (sizeof (entry
) * newsize
);
131 memset (newtable
, 0, newsize
* sizeof (entry
));
133 for (i
= 0; i
< ht
->tablelength
; i
++) {
134 for (e
= ht
->table
[i
]; e
; e
= ne
) {
136 index
= INDEX_FOR (e
->hash
, newsize
);
137 e
->next
= newtable
[index
];
142 fixedpool_grow (ht
->pool
->entrypool
, ht
->table
, ht
->tablelength
);
144 ht
->table
= newtable
;
145 ht
->tablelength
= newsize
;
146 ht
->loadlimit
= newsize
>> 1;
149 unsigned int hashtable_count (hashtable ht
)
151 return ht
->entrycount
;
154 void hashtable_insert (hashtable ht
, void *key
, void *value
)
156 hashtable_inserthash (ht
, key
, value
, ht
->hashfn (key
));
159 void hashtable_inserthash (hashtable ht
, void *key
, void *value
, unsigned int hash
)
164 if (ht
->entrycount
>= ht
->loadlimit
) {
168 e
= alloc_entry (ht
->pool
);
170 index
= INDEX_FOR (e
->hash
, ht
->tablelength
);
173 e
->next
= ht
->table
[index
];
175 ht
->table
[index
] = e
;
180 entry
find_entry (hashtable ht
, void *key
, unsigned int hash
, int remove
)
186 index
= INDEX_FOR (hash
, ht
->tablelength
);
187 for (prev
= &(ht
->table
[index
]); (e
= *prev
) ; prev
= &e
->next
) {
188 if (hash
!= e
->hash
) continue;
190 if (!ht
->eqfn (key
, e
->key
, hash
))
196 free_entry (ht
->pool
, e
);
204 void *hashtable_search (hashtable ht
, void *key
, void **key_found
)
206 return hashtable_searchhash (ht
, key
, key_found
, ht
->hashfn (key
));
209 void *hashtable_searchhash (hashtable ht
, void *key
, void **key_found
, unsigned int hash
)
212 e
= find_entry (ht
, key
, hash
, 0);
221 int hashtable_haskey (hashtable ht
, void *key
, void **key_found
)
223 return hashtable_haskeyhash (ht
, key
, key_found
, ht
->hashfn (key
));
226 int hashtable_haskeyhash (hashtable ht
, void *key
, void **key_found
, unsigned int hash
)
228 entry e
= find_entry (ht
, key
, hash
, 0);
237 void *hashtable_remove (hashtable ht
, void *key
, void **key_found
)
239 return hashtable_removehash (ht
, key
, key_found
, ht
->hashfn (key
));
242 void *hashtable_removehash (hashtable ht
, void *key
, void **key_found
, unsigned int hash
)
244 entry e
= find_entry (ht
, key
, hash
, 1);
254 void hashtable_traverse (hashtable ht
, hashtraversefn traversefn
, void *arg
)
259 for (i
= 0; i
< ht
->tablelength
; i
++) {
260 for (e
= ht
->table
[i
]; e
; e
= e
->next
) {
261 traversefn (e
->key
, e
->value
, e
->hash
, arg
);
266 int hashtable_string_compare (void *key1
, void *key2
, unsigned int hash
)
268 return (strcmp (key1
, key2
) == 0);
271 int hashtable_pointer_compare (void *key1
, void *key2
, unsigned int hash
)
273 return (key1
== key2
);
277 unsigned int hashtable_hash_bytes (unsigned char *key
, size_t len
)
279 unsigned int hash
= 0;
282 for (i
= 0; i
< len
; i
++) {
284 hash
+= (hash
<< 10);
289 hash
^= (hash
>> 11);
290 hash
+= (hash
<< 15);
295 unsigned int hashtable_hash_string (void *key
)
297 unsigned int hash
= 0;
298 unsigned char *bytes
= (unsigned char *) key
;
302 hash
+= (hash
<< 10);
307 hash
^= (hash
>> 11);
308 hash
+= (hash
<< 15);