Now my comments should be in english....
[pspdecompiler.git] / hash.c
blob09afbe68b812fab894e0453236511bd114bc1bee
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 */
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <math.h>
10 #include "hash.h"
11 #include "alloc.h"
12 #include "utils.h"
13 #include "types.h"
15 #define INDEX_FOR(hash, size) ((hash) & ((size) - 1))
17 struct _entry {
18 void *key, *value;
19 unsigned int hash;
20 struct _entry *next;
23 typedef struct _entry *entry;
25 struct _hashtable {
26 struct _hashpool *const pool;
27 unsigned int tablelength;
28 unsigned int entrycount;
29 unsigned int loadlimit;
30 struct _entry **table;
31 hashfn hashfn;
32 hashequalsfn eqfn;
35 struct _hashpool {
36 fixedpool tablepool;
37 fixedpool entrypool;
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);
46 return pool;
49 static
50 void destroy_hashtable (void *ptr, void *arg)
52 hashtable ht = ptr;
53 if (ht->table) {
54 free (ht->table);
55 ht->table = NULL;
59 void hashpool_destroy (hashpool pool)
61 fixedpool_destroy (pool->tablepool, &destroy_hashtable, NULL);
62 fixedpool_destroy (pool->entrypool, NULL, NULL);
63 free (pool);
66 static
67 entry alloc_entry (hashpool pool)
69 return fixedpool_alloc (pool->entrypool);
72 static
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)
81 hashtable ht;
82 hashpool *ptr;
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;
89 *ptr = pool;
91 ht->tablelength = size;
92 ht->entrycount = 0;
93 ht->hashfn = hashfn;
94 ht->eqfn = eqfn;
95 ht->loadlimit = size >> 1;
97 return ht;
100 void hashtable_free (hashtable ht, hashtraversefn destroyfn, void *arg)
102 entry e;
103 unsigned int i;
105 for (i = 0; i < ht->tablelength; i++) {
106 for (e = ht->table[i]; e; e = e->next) {
107 if (destroyfn)
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);
114 ht->table = NULL;
115 ht->tablelength = 0;
116 ht->entrycount = 0;
118 fixedpool_free (ht->pool->tablepool, ht);
121 static
122 void hashtable_grow (hashtable ht)
124 entry *newtable;
125 entry e, ne;
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) {
135 ne = e->next;
136 index = INDEX_FOR (e->hash, newsize);
137 e->next = newtable[index];
138 newtable[index] = e;
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)
161 unsigned int index;
162 entry e;
164 if (ht->entrycount >= ht->loadlimit) {
165 hashtable_grow (ht);
168 e = alloc_entry (ht->pool);
169 e->hash = hash;
170 index = INDEX_FOR (e->hash, ht->tablelength);
171 e->key = key;
172 e->value = value;
173 e->next = ht->table[index];
174 ht->entrycount++;
175 ht->table[index] = e;
179 static
180 entry find_entry (hashtable ht, void *key, unsigned int hash, int remove)
182 entry e;
183 entry *prev;
184 unsigned int index;
186 index = INDEX_FOR (hash, ht->tablelength);
187 for (prev = &(ht->table[index]); (e = *prev) ; prev = &e->next) {
188 if (hash != e->hash) continue;
189 if (key != e->key)
190 if (!ht->eqfn (key, e->key, hash))
191 continue;
193 if (remove) {
194 *prev = e->next;
195 ht->entrycount--;
196 free_entry (ht->pool, e);
199 return e;
201 return NULL;
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)
211 entry e;
212 e = find_entry (ht, key, hash, 0);
213 if (e) {
214 if (key_found)
215 *key_found = e->key;
216 return e->value;
218 return NULL;
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);
229 if (e) {
230 if (key_found)
231 *key_found = e->key;
232 return TRUE;
234 return FALSE;
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);
245 if (e) {
246 if (key_found)
247 *key_found = e->key;
248 return e->value;
250 return NULL;
254 void hashtable_traverse (hashtable ht, hashtraversefn traversefn, void *arg)
256 entry e;
257 unsigned int i;
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;
280 size_t i;
282 for (i = 0; i < len; i++) {
283 hash += key[i];
284 hash += (hash << 10);
285 hash ^= (hash >> 6);
288 hash += (hash << 3);
289 hash ^= (hash >> 11);
290 hash += (hash << 15);
292 return hash;
295 unsigned int hashtable_hash_string (void *key)
297 unsigned int hash = 0;
298 unsigned char *bytes = (unsigned char *) key;
300 while (*bytes) {
301 hash += *bytes++;
302 hash += (hash << 10);
303 hash ^= (hash >> 6);
306 hash += (hash << 3);
307 hash ^= (hash >> 11);
308 hash += (hash << 15);
310 return hash;