Problemas com os relocs
[pspdecompiler.git] / hash.c
blob1536b306451b8b9fde47458558a57da36c8fdf8b
2 #include <stddef.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
7 #include "hash.h"
8 #include "utils.h"
9 #include "types.h"
11 #define DEFAULT_ALLOC_ENTRIES 512
12 #define INDEX_FOR(hash, size) ((hash) & ((size) - 1))
14 struct entry {
15 void *key, *value;
16 unsigned int hash;
17 struct entry *next;
20 struct hashtable {
21 unsigned int tablelength;
22 unsigned int entrycount;
23 unsigned int loadlimit;
24 struct entry **table;
25 hashfunction hashfn;
26 equalsfunction eqfn;
28 struct entry *alloclist;
29 struct entry *nextavail;
33 static
34 struct entry *alloc_entry (struct hashtable *ht)
36 struct entry *e;
37 if (!ht->nextavail) {
38 int i;
39 e = (struct entry *) xmalloc (DEFAULT_ALLOC_ENTRIES * sizeof (struct entry));
40 e->next = ht->alloclist;
41 ht->alloclist = e;
43 for (i = 1; i < DEFAULT_ALLOC_ENTRIES - 1; i++)
44 e[i].next = &e[i + 1];
45 e[i].next = NULL;
47 ht->nextavail = &e[1];
49 e = ht->nextavail;
50 ht->nextavail = e->next;
51 return e;
54 static
55 void free_entry (struct hashtable *ht, struct entry *e)
57 e->next = ht->nextavail;
58 ht->nextavail = e;
61 struct hashtable *hashtable_create (unsigned int size, hashfunction hashfn, equalsfunction eqfn)
63 struct hashtable *ht;
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;
70 ht->entrycount = 0;
71 ht->hashfn = hashfn;
72 ht->eqfn = eqfn;
73 ht->loadlimit = size >> 1;
74 ht->alloclist = NULL;
75 ht->nextavail = NULL;
77 return ht;
80 void hashtable_free (struct hashtable *ht, traversefunction destroyfn, void *arg)
82 struct entry *e, *ne;
84 if (destroyfn)
85 hashtable_traverse (ht, destroyfn, arg);
87 for (e = ht->alloclist; e; e = ne) {
88 ne = e->next;
89 free (e);
92 free (ht->table);
93 free (ht);
96 static
97 void free_all_callback (void *key, void *value, unsigned int hash, void *arg)
99 if (key) free (key);
100 if (value) free (value);
103 void hashtable_free_all (struct hashtable *ht)
105 hashtable_free (ht, &free_all_callback, NULL);
109 static
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) {
123 ne = e->next;
124 index = INDEX_FOR (e->hash, newsize);
125 e->next = newtable[index];
126 newtable[index] = e;
130 free (ht->table);
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)
148 unsigned int index;
149 struct entry *e;
151 if (ht->entrycount >= ht->loadlimit) {
152 hashtable_grow (ht);
154 e = alloc_entry (ht);
155 e->hash = hash;
156 index = INDEX_FOR (e->hash, ht->tablelength);
157 e->key = key;
158 e->value = value;
159 e->next = ht->table[index];
160 ht->entrycount++;
161 ht->table[index] = e;
165 static
166 struct entry *find_entry (struct hashtable *ht, void *key, unsigned int hash, int remove)
168 struct entry *e;
169 struct entry **prev;
170 unsigned int index;
172 index = INDEX_FOR (hash, ht->tablelength);
173 for (prev = &(ht->table[index]); (e = *prev) ; prev = &e->next) {
174 if (hash != e->hash) continue;
175 if (key != e->key)
176 if (!ht->eqfn (key, e->key, hash))
177 continue;
179 if (remove) {
180 *prev = e->next;
181 ht->entrycount--;
182 free_entry (ht, e);
185 return e;
187 return NULL;
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);
198 if (e) {
199 if (key_found)
200 *key_found = e->key;
201 return e->value;
203 return NULL;
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);
214 if (e) {
215 if (key_found)
216 *key_found = e->key;
217 return TRUE;
219 return FALSE;
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);
230 if (e) {
231 if (key_found)
232 *key_found = e->key;
233 return e->value;
235 return NULL;
239 void hashtable_traverse (struct hashtable *ht, traversefunction traversefn, void *arg)
241 struct entry *e;
242 unsigned int i;
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;
265 size_t i;
267 for (i = 0; i < len; i++) {
268 hash += key[i];
269 hash += (hash << 10);
270 hash ^= (hash >> 6);
273 hash += (hash << 3);
274 hash ^= (hash >> 11);
275 hash += (hash << 15);
277 return hash;
280 unsigned int hashtable_hash_string (void *key)
282 unsigned int hash = 0;
283 unsigned char *bytes = (unsigned char *) key;
285 while (*bytes) {
286 hash += *bytes++;
287 hash += (hash << 10);
288 hash ^= (hash >> 6);
291 hash += (hash << 3);
292 hash ^= (hash >> 11);
293 hash += (hash << 15);
295 return hash;