12 #define INDEX_FOR(hash, size) ((hash) & ((size) - 1))
20 typedef struct _entry
*entry
;
23 struct _hashpool
*const pool
;
24 unsigned int tablelength
;
25 unsigned int entrycount
;
26 unsigned int loadlimit
;
27 struct _entry
**table
;
38 hashpool
hashpool_create (size_t numtables
, size_t numentries
)
40 hashpool pool
= (hashpool
) xmalloc (sizeof (struct _hashpool
));
41 pool
->tablepool
= fixedpool_create (sizeof (struct _hashtable
), numtables
, 0);
42 pool
->entrypool
= fixedpool_create (sizeof (struct _entry
), numentries
, 0);
47 void destroy_hashtable (void *ptr
, void *arg
)
56 void hashpool_destroy (hashpool pool
)
58 fixedpool_destroy (pool
->tablepool
, &destroy_hashtable
, NULL
);
59 fixedpool_destroy (pool
->entrypool
, NULL
, NULL
);
64 entry
alloc_entry (hashpool pool
)
66 return fixedpool_alloc (pool
->entrypool
);
70 void free_entry (hashpool pool
, entry e
)
72 fixedpool_free (pool
->entrypool
, e
);
76 hashtable
hashtable_alloc (hashpool pool
, unsigned int size
, hashfn hashfn
, hashequalsfn eqfn
)
81 ht
= fixedpool_alloc (pool
->tablepool
);
82 ht
->table
= (entry
*) xmalloc (sizeof (entry
) * size
);
83 memset (ht
->table
, 0, size
* sizeof (entry
));
85 ptr
= (hashpool
*) &ht
->pool
;
88 ht
->tablelength
= size
;
92 ht
->loadlimit
= size
>> 1;
97 void hashtable_free (hashtable ht
, hashtraversefn destroyfn
, void *arg
)
102 for (i
= 0; i
< ht
->tablelength
; i
++) {
103 for (e
= ht
->table
[i
]; e
; e
= e
->next
) {
105 destroyfn (e
->key
, e
->value
, e
->hash
, arg
);
106 fixedpool_free (ht
->pool
->entrypool
, e
);
110 fixedpool_grow (ht
->pool
->entrypool
, ht
->table
, ht
->tablelength
);
115 fixedpool_free (ht
->pool
->tablepool
, ht
);
119 void hashtable_grow (hashtable ht
)
123 unsigned int newsize
, i
, index
;
125 newsize
= ht
->tablelength
<< 1;
127 newtable
= (entry
*) xmalloc (sizeof (entry
) * newsize
);
128 memset (newtable
, 0, newsize
* sizeof (entry
));
130 for (i
= 0; i
< ht
->tablelength
; i
++) {
131 for (e
= ht
->table
[i
]; e
; e
= ne
) {
133 index
= INDEX_FOR (e
->hash
, newsize
);
134 e
->next
= newtable
[index
];
139 fixedpool_grow (ht
->pool
->entrypool
, ht
->table
, ht
->tablelength
);
141 ht
->table
= newtable
;
142 ht
->tablelength
= newsize
;
143 ht
->loadlimit
= newsize
>> 1;
146 unsigned int hashtable_count (hashtable ht
)
148 return ht
->entrycount
;
151 void hashtable_insert (hashtable ht
, void *key
, void *value
)
153 hashtable_inserthash (ht
, key
, value
, ht
->hashfn (key
));
156 void hashtable_inserthash (hashtable ht
, void *key
, void *value
, unsigned int hash
)
161 if (ht
->entrycount
>= ht
->loadlimit
) {
165 e
= alloc_entry (ht
->pool
);
167 index
= INDEX_FOR (e
->hash
, ht
->tablelength
);
170 e
->next
= ht
->table
[index
];
172 ht
->table
[index
] = e
;
177 entry
find_entry (hashtable ht
, void *key
, unsigned int hash
, int remove
)
183 index
= INDEX_FOR (hash
, ht
->tablelength
);
184 for (prev
= &(ht
->table
[index
]); (e
= *prev
) ; prev
= &e
->next
) {
185 if (hash
!= e
->hash
) continue;
187 if (!ht
->eqfn (key
, e
->key
, hash
))
193 free_entry (ht
->pool
, e
);
201 void *hashtable_search (hashtable ht
, void *key
, void **key_found
)
203 return hashtable_searchhash (ht
, key
, key_found
, ht
->hashfn (key
));
206 void *hashtable_searchhash (hashtable ht
, void *key
, void **key_found
, unsigned int hash
)
209 e
= find_entry (ht
, key
, hash
, 0);
218 int hashtable_haskey (hashtable ht
, void *key
, void **key_found
)
220 return hashtable_haskeyhash (ht
, key
, key_found
, ht
->hashfn (key
));
223 int hashtable_haskeyhash (hashtable ht
, void *key
, void **key_found
, unsigned int hash
)
225 entry e
= find_entry (ht
, key
, hash
, 0);
234 void *hashtable_remove (hashtable ht
, void *key
, void **key_found
)
236 return hashtable_removehash (ht
, key
, key_found
, ht
->hashfn (key
));
239 void *hashtable_removehash (hashtable ht
, void *key
, void **key_found
, unsigned int hash
)
241 entry e
= find_entry (ht
, key
, hash
, 1);
251 void hashtable_traverse (hashtable ht
, hashtraversefn traversefn
, void *arg
)
256 for (i
= 0; i
< ht
->tablelength
; i
++) {
257 for (e
= ht
->table
[i
]; e
; e
= e
->next
) {
258 traversefn (e
->key
, e
->value
, e
->hash
, arg
);
263 int hashtable_string_compare (void *key1
, void *key2
, unsigned int hash
)
265 return (strcmp (key1
, key2
) == 0);
268 int hashtable_pointer_compare (void *key1
, void *key2
, unsigned int hash
)
270 return (key1
== key2
);
274 unsigned int hashtable_hash_bytes (unsigned char *key
, size_t len
)
276 unsigned int hash
= 0;
279 for (i
= 0; i
< len
; i
++) {
281 hash
+= (hash
<< 10);
286 hash
^= (hash
>> 11);
287 hash
+= (hash
<< 15);
292 unsigned int hashtable_hash_string (void *key
)
294 unsigned int hash
= 0;
295 unsigned char *bytes
= (unsigned char *) key
;
299 hash
+= (hash
<< 10);
304 hash
^= (hash
>> 11);
305 hash
+= (hash
<< 15);