11 #define DEFAULT_ALLOC_ENTRIES 512
12 #define INDEX_FOR(hash, size) ((hash) & ((size) - 1))
21 unsigned int tablelength
;
22 unsigned int entrycount
;
23 unsigned int loadlimit
;
28 struct entry
*alloclist
;
29 struct entry
*nextavail
;
34 struct entry
*alloc_entry (struct hashtable
*ht
)
39 e
= (struct entry
*) xmalloc (DEFAULT_ALLOC_ENTRIES
* sizeof (struct entry
));
40 e
->next
= ht
->alloclist
;
43 for (i
= 1; i
< DEFAULT_ALLOC_ENTRIES
- 1; i
++)
44 e
[i
].next
= &e
[i
+ 1];
47 ht
->nextavail
= &e
[1];
50 ht
->nextavail
= e
->next
;
55 void free_entry (struct hashtable
*ht
, struct entry
*e
)
57 e
->next
= ht
->nextavail
;
61 struct hashtable
*hashtable_create (unsigned int size
, hashfunction hashfn
, equalsfunction eqfn
)
65 ht
= (struct hashtable
*) xmalloc (sizeof (struct hashtable
));
66 ht
->table
= (struct entry
**) xmalloc (sizeof (struct entry
*) * size
);
67 memset (ht
->table
, 0, size
* sizeof (struct entry
*));
69 ht
->tablelength
= size
;
73 ht
->loadlimit
= size
>> 1;
80 void hashtable_free (struct hashtable
*ht
, traversefunction destroyfn
, void *arg
)
85 hashtable_traverse (ht
, destroyfn
, arg
);
87 for (e
= ht
->alloclist
; e
; e
= ne
) {
97 void free_all_callback (void *key
, void *value
, unsigned int hash
, void *arg
)
100 if (value
) free (value
);
103 void hashtable_free_all (struct hashtable
*ht
)
105 hashtable_free (ht
, &free_all_callback
, NULL
);
110 void hashtable_grow (struct hashtable
*ht
)
112 struct entry
**newtable
;
113 struct entry
*e
, *ne
;
114 unsigned int newsize
, i
, index
;
116 newsize
= ht
->tablelength
<< 1;
118 newtable
= (struct entry
**) xmalloc (sizeof (struct entry
*) * newsize
);
119 memset (newtable
, 0, newsize
* sizeof (struct entry
*));
121 for (i
= 0; i
< ht
->tablelength
; i
++) {
122 for (e
= ht
->table
[i
]; e
; e
= ne
) {
124 index
= INDEX_FOR (e
->hash
, newsize
);
125 e
->next
= newtable
[index
];
131 ht
->table
= newtable
;
132 ht
->tablelength
= newsize
;
133 ht
->loadlimit
= newsize
>> 1;
136 unsigned int hashtable_count (struct hashtable
*ht
)
138 return ht
->entrycount
;
141 void hashtable_insert (struct hashtable
*ht
, void *key
, void *value
)
143 hashtable_inserth (ht
, key
, value
, ht
->hashfn (key
));
146 void hashtable_inserth (struct hashtable
*ht
, void *key
, void *value
, unsigned int hash
)
151 if (ht
->entrycount
>= ht
->loadlimit
) {
154 e
= alloc_entry (ht
);
156 index
= INDEX_FOR (e
->hash
, ht
->tablelength
);
159 e
->next
= ht
->table
[index
];
161 ht
->table
[index
] = e
;
166 struct entry
*find_entry (struct hashtable
*ht
, void *key
, unsigned int hash
, int remove
)
172 index
= INDEX_FOR (hash
, ht
->tablelength
);
173 for (prev
= &(ht
->table
[index
]); (e
= *prev
) ; prev
= &e
->next
) {
174 if (hash
!= e
->hash
) continue;
176 if (!ht
->eqfn (key
, e
->key
, hash
))
190 void *hashtable_search (struct hashtable
*ht
, void *key
, void **key_found
)
192 return hashtable_searchh (ht
, key
, key_found
, ht
->hashfn (key
));
195 void *hashtable_searchh (struct hashtable
*ht
, void *key
, void **key_found
, unsigned int hash
)
197 struct entry
*e
= find_entry (ht
, key
, hash
, 0);
206 int hashtable_haskey (struct hashtable
*ht
, void *key
, void **key_found
)
208 return hashtable_haskeyh (ht
, key
, key_found
, ht
->hashfn (key
));
211 int hashtable_haskeyh (struct hashtable
*ht
, void *key
, void **key_found
, unsigned int hash
)
213 struct entry
*e
= find_entry (ht
, key
, hash
, 0);
222 void *hashtable_remove (struct hashtable
*ht
, void *key
, void **key_found
)
224 return hashtable_removeh (ht
, key
, key_found
, ht
->hashfn (key
));
227 void *hashtable_removeh (struct hashtable
*ht
, void *key
, void **key_found
, unsigned int hash
)
229 struct entry
*e
= find_entry (ht
, key
, hash
, 1);
239 void hashtable_traverse (struct hashtable
*ht
, traversefunction traversefn
, void *arg
)
244 for (i
= 0; i
< ht
->tablelength
; i
++) {
245 for (e
= ht
->table
[i
]; e
; e
= e
->next
) {
246 traversefn (e
->key
, e
->value
, e
->hash
, arg
);
251 int hashtable_string_compare (void *key1
, void *key2
, unsigned int hash
)
253 return (strcmp (key1
, key2
) == 0);
256 int hashtable_pointer_compare (void *key1
, void *key2
, unsigned int hash
)
258 return (key1
== key2
);
262 unsigned int hashtable_hash_bytes (unsigned char *key
, size_t len
)
264 unsigned int hash
= 0;
267 for (i
= 0; i
< len
; i
++) {
269 hash
+= (hash
<< 10);
274 hash
^= (hash
>> 11);
275 hash
+= (hash
<< 15);
280 unsigned int hashtable_hash_string (void *key
)
282 unsigned int hash
= 0;
283 unsigned char *bytes
= (unsigned char *) key
;
287 hash
+= (hash
<< 10);
292 hash
^= (hash
>> 11);
293 hash
+= (hash
<< 15);