wrong version committed
[AROS.git] / rom / oop / hash.c
blobc68d927d15dd1429f0f22cab8e8098db5c06953d
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Common code for handling hashing.
6 Lang: english
7 */
9 #include "hash.h"
10 #include "intern.h"
12 #include <proto/exec.h>
13 #include <exec/memory.h>
14 #include <stdlib.h>
16 #undef SDEBUG
17 #undef DEBUG
18 #define SDEBUG 0
19 #define DEBUG 0
20 #include <aros/debug.h>
22 #include <string.h>
24 #define UB(x) ((UBYTE *)x)
26 /******************
27 ** AllocHash() **
28 ******************/
30 /* Allocates a hashtable for given number of entries,
31 ** so that hash table is no more than 50% full.
32 ** Initializes table as empty.
35 struct HashTable *NewHash(ULONG entries, UBYTE type, struct IntOOPBase *OOPBase)
39 ULONG temp = 1;
40 BYTE i;
41 ULONG size;
42 struct HashTable *ht;
44 EnterFunc(bug("NewHash(entries=%ld, type=%ld)\n", entries, type));
46 /* Allocate hashtable struct */
49 ht = AllocMem(sizeof (struct HashTable), MEMF_ANY);
50 if (ht)
52 /* Allocate table of size 2^n - 1 */
53 /* Find the highest bit in 'initial' */
54 for (i = 31; i >= 0; i --)
56 if ((temp << i) & entries)
57 break;
60 D(bug("i: %d\n", i));
62 /* Make sure table is never more than 50% full */
63 i ++;
65 entries = (temp << i);
66 entries --; /* 2^n - 1 */
68 /* Get table size */
69 size = UB( &ht[entries] ) - UB( &ht[0] );
71 /* Allocate the table */
72 ht->Table = AllocVec(size, MEMF_ANY|MEMF_CLEAR);
73 if (ht)
75 ht->HashMask = entries - 1;
76 ht->Type = type;
78 /* Initialize the hashtable's Lookup and CalcHash
79 ** accordint to if we want to hash integers or strings
81 switch (type)
83 case HT_INTEGER:
84 ht->Lookup = HashLookupULONG;
85 ht->CalcHash = CalcHashULONG;
86 break;
88 case HT_STRING:
89 ht->Lookup = HashLookupStr;
90 ht->CalcHash = CalcHashStr;
91 break;
96 ReturnPtr ("NewHash", struct HashTable *, ht);
98 FreeMem(ht, sizeof (struct HashTable));
100 ReturnPtr ("NewHash", struct HashTable *, NULL);
103 /*****************
104 ** FreeHash() **
105 *****************/
106 VOID FreeHash(struct HashTable *ht, VOID (*freebucket)(), struct IntOOPBase *OOPBase)
108 ULONG i;
110 EnterFunc(bug("FreeHash(ht=%p, freebucket=%p)\n", ht, freebucket));
112 D(bug("Hashsize: %ld\n", HashSize(ht) ));
115 /* Free all buckets */
116 for (i = 0; i < HashSize(ht); i ++)
118 struct Bucket *b, *next_b;
119 D(bug("Freeing buckets at entry %ld\n", i));
121 for (b = ht->Table[i]; b; b = next_b)
123 next_b = b->Next;
124 /* USe usersupplied func to free bucket */
125 freebucket(b, OOPBase);
128 /* Free the table */
129 FreeVec(ht->Table);
130 /* Free the hashtable struct */
131 FreeMem(ht, sizeof (struct HashTable));
133 ReturnVoid("FreeHash");
136 /*******************
137 ** HashLookup() **
138 *******************/
139 struct Bucket *HashLookupULONG(struct HashTable *ht, IPTR id, struct IntOOPBase *OOPBase)
141 struct Bucket *b;
142 EnterFunc(bug("HashLookupULONG(ht=%p, id=%ld)\n", ht, id));
143 /* Function for looking up integers in the table */
144 for (b = ht->Table[CalcHashULONG(ht, id)]; b; b = b->Next)
146 D(bug("Current bucket: %p of id %ld\n", b, b->ID));
147 if (b->ID == id)
148 ReturnPtr ("HashLookupULONG", struct Bucket *, b);
151 ReturnPtr ("HashLookupULONG", struct Bucket *, NULL);
154 struct Bucket *HashLookupStr(struct HashTable *ht, IPTR id, struct IntOOPBase *OOPBase)
156 struct Bucket *b;
158 /* Function for looking up strings in the table */
159 EnterFunc(bug("HashLookupStr(ht=%p, id=%s)\n", ht, (STRPTR)id));
160 for (b = ht->Table[CalcHashStr(ht, id)]; b; b = b->Next)
162 D(bug("Bucket: %p\n", b));
163 D(bug("ID: %p\n", b->ID));
164 D(bug("ID: %s\n", b->ID));
165 if (!strcmp((STRPTR)b->ID, (STRPTR)id))
166 ReturnPtr ("HashLookupStr", struct Bucket *, b);
168 ReturnPtr ("HashLookupStr", struct Bucket *, NULL);
171 /*****************
172 ** CopyHash() **
173 *****************/
174 BOOL CopyHash(struct HashTable *dest_ht
175 ,struct HashTable *src_ht
176 ,struct Bucket * (*copybucket)()
177 ,APTR data
178 ,struct IntOOPBase *OOPBase )
180 ULONG i;
182 /* Copies all buckets of src_ht into dest_ht */
184 EnterFunc(bug("CopyHash(dest_ht=%p, src_ht=%p, copybucket=%p,data = %p)\n",
185 dest_ht, src_ht, copybucket, data));
187 /* for each entry in the table */
188 for (i = 0; i < HashSize(src_ht); i ++ )
190 struct Bucket *b;
192 D(bug("idx: %ld\n", i));
194 /* for each bucket at curent entry */
195 for (b = src_ht->Table[i]; b; b = b->Next)
197 /* Rehash bucket into destination hashtable */
198 struct Bucket *new_b;
200 D(bug("Bucket: %p\n", b));
202 /* use user-supllied func to copy the bucket */
203 new_b = copybucket(b, data, OOPBase);
204 if (!new_b)
205 ReturnBool ("CopyHash", FALSE);
207 /* insert the new bucket into detsination table */
208 InsertBucket(dest_ht, new_b, OOPBase);
211 } /* For each bucket at current entry */
213 } /* For each entry in source hashtable */
215 ReturnBool ("CopyHash", TRUE);
218 /*********************
219 ** InsertBucket() **
220 *********************/
221 VOID InsertBucket(struct HashTable *ht, struct Bucket *b, struct IntOOPBase *OOPBase)
223 /* Inserts bucket into hashtable according to its ID */
224 ULONG idx;
226 EnterFunc(bug("InsertBucket(ht=%p, b=%p)\n", ht, b));
228 idx = ht->CalcHash(ht, b->ID);
229 b->Next = ht->Table[idx];
230 ht->Table[idx] = b;
231 D(bug("b->Next=%p\n", b->Next));
233 ReturnVoid ("InsertBucket");
237 VOID RemoveBucket(struct HashTable *ht, struct Bucket *b)
239 ULONG idx;
240 struct Bucket *last_b = NULL,
241 *cur_b;
242 idx = ht->CalcHash(ht, b->ID);
244 /* Search for bucket to remove */
245 for (cur_b = ht->Table[idx]; cur_b; cur_b = cur_b->Next)
247 if (cur_b == b)
249 /* Bucket found */
250 if (last_b)
252 /* Remove bucket from chain */
253 last_b->Next = cur_b->Next;
255 /* Not really neccessar, but ... */
256 b->Next = NULL;
258 else
260 /* We are removing the first bucket */
261 ht->Table[idx] = cur_b->Next;
265 last_b = cur_b;
267 } /* for (each bucket at idx) */
272 ULONG CalcHashULONG(struct HashTable *ht, IPTR id)
274 /* Return idx into hashtable for an integer */
275 return (id % HashMask(ht));
278 static ULONG CalcHashStr_KR(struct HashTable *ht, IPTR id)
280 STRPTR str = (STRPTR)id;
281 ULONG val, i;
282 /* Return idx into hashtable for a string */
283 for (i = 0, val = 0; (i < MAX_HASH_CHARS) && *str; str ++)
284 {val += *str; i ++; }
286 return (val & HashSize(ht));
289 #if 0 /* Unused */
290 static ULONG CalcHashStr_DJB2(struct HashTable *ht, IPTR id)
292 STRPTR str = (STRPTR)id;
293 ULONG val, i;
294 /* Return idx into hashtable for a string */
295 for (i = 0, val = 0; (i < MAX_HASH_CHARS) && *str; str ++)
296 {val = ((val << 5) + val) ^ *str; i ++; }
298 return (val & HashSize(ht));
300 #endif
302 ULONG CalcHashStr_SDBM(struct HashTable *ht, IPTR id)
304 STRPTR str = (STRPTR)id;
305 ULONG val, i;
306 /* Return idx into hashtable for a string */
307 for (i = 0, val = 0; (i < MAX_HASH_CHARS) && *str; str ++)
308 {val = *str + (val << 6) + (val << 16) - val; i ++; }
310 return (val & HashSize(ht));
313 ULONG CalcHashStr_Org(struct HashTable *ht, IPTR id)
315 STRPTR str = (STRPTR)id;
316 ULONG val, i;
317 /* Return idx into hashtable for a string */
318 for (i = 0, val = 0; (i < MAX_HASH_CHARS) && *str; str ++)
319 {val += *str; i ++; }
321 return (val & HashSize(ht));
324 ULONG CalcHashStr(struct HashTable *ht, IPTR id)
326 return CalcHashStr_KR(ht, id);
329 /* Prints contents of a hastable */
330 VOID print_table(struct HashTable *ht, struct IntOOPBase *OOPBase)
332 ULONG idx;
333 ULONG filled=0;
335 for (idx = 0; idx < HashSize(ht); idx ++)
337 struct Bucket *b;
338 BOOL ok = FALSE;
339 D(bug("idx %ld: ", idx));
340 for (b = ht->Table[idx]; b; b = b->Next)
342 ok = TRUE;
343 #if DEBUG
344 if (ht->Type == HT_INTEGER)
345 bug("%ld ", b->ID);
346 else
347 bug("%s(%ld) ", (STRPTR)b->ID, ((struct iid_bucket *)b)->refcount);
348 #endif
350 D(bug("\n"));
351 if (ok) filled++;
354 D(bug("HashTable fill ratio: %d %%\n", filled * 100 / HashSize(ht)));
355 return;