2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Common code for handling hashing.
12 #include <proto/exec.h>
13 #include <exec/memory.h>
20 #include <aros/debug.h>
24 #define UB(x) ((UBYTE *)x)
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
)
44 EnterFunc(bug("NewHash(entries=%ld, type=%ld)\n", entries
, type
));
46 /* Allocate hashtable struct */
49 ht
= AllocMem(sizeof (struct HashTable
), MEMF_ANY
);
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
)
62 /* Make sure table is never more than 50% full */
65 entries
= (temp
<< i
);
66 entries
--; /* 2^n - 1 */
69 size
= UB( &ht
[entries
] ) - UB( &ht
[0] );
71 /* Allocate the table */
72 ht
->Table
= AllocVec(size
, MEMF_ANY
|MEMF_CLEAR
);
75 ht
->HashMask
= entries
- 1;
78 /* Initialize the hashtable's Lookup and CalcHash
79 ** accordint to if we want to hash integers or strings
84 ht
->Lookup
= HashLookupULONG
;
85 ht
->CalcHash
= CalcHashULONG
;
89 ht
->Lookup
= HashLookupStr
;
90 ht
->CalcHash
= CalcHashStr
;
96 ReturnPtr ("NewHash", struct HashTable
*, ht
);
98 FreeMem(ht
, sizeof (struct HashTable
));
100 ReturnPtr ("NewHash", struct HashTable
*, NULL
);
106 VOID
FreeHash(struct HashTable
*ht
, VOID (*freebucket
)(), struct IntOOPBase
*OOPBase
)
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
)
124 /* USe usersupplied func to free bucket */
125 freebucket(b
, OOPBase
);
130 /* Free the hashtable struct */
131 FreeMem(ht
, sizeof (struct HashTable
));
133 ReturnVoid("FreeHash");
139 struct Bucket
*HashLookupULONG(struct HashTable
*ht
, IPTR id
, struct IntOOPBase
*OOPBase
)
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
));
148 ReturnPtr ("HashLookupULONG", struct Bucket
*, b
);
151 ReturnPtr ("HashLookupULONG", struct Bucket
*, NULL
);
154 struct Bucket
*HashLookupStr(struct HashTable
*ht
, IPTR id
, struct IntOOPBase
*OOPBase
)
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
);
174 BOOL
CopyHash(struct HashTable
*dest_ht
175 ,struct HashTable
*src_ht
176 ,struct Bucket
* (*copybucket
)()
178 ,struct IntOOPBase
*OOPBase
)
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
++ )
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
);
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 /*********************
220 *********************/
221 VOID
InsertBucket(struct HashTable
*ht
, struct Bucket
*b
, struct IntOOPBase
*OOPBase
)
223 /* Inserts bucket into hashtable according to its ID */
226 EnterFunc(bug("InsertBucket(ht=%p, b=%p)\n", ht
, b
));
228 idx
= ht
->CalcHash(ht
, b
->ID
);
229 b
->Next
= ht
->Table
[idx
];
231 D(bug("b->Next=%p\n", b
->Next
));
233 ReturnVoid ("InsertBucket");
237 VOID
RemoveBucket(struct HashTable
*ht
, struct Bucket
*b
)
240 struct Bucket
*last_b
= NULL
,
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
)
252 /* Remove bucket from chain */
253 last_b
->Next
= cur_b
->Next
;
255 /* Not really neccessar, but ... */
260 /* We are removing the first bucket */
261 ht
->Table
[idx
] = cur_b
->Next
;
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
;
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 static ULONG
CalcHashStr_DJB2(struct HashTable
*ht
, IPTR id
)
291 STRPTR str
= (STRPTR
)id
;
293 /* Return idx into hashtable for a string */
294 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
295 {val
= ((val
<< 5) + val
) ^ *str
; i
++; }
297 return (val
& HashSize(ht
));
300 ULONG
CalcHashStr_SDBM(struct HashTable
*ht
, IPTR id
)
302 STRPTR str
= (STRPTR
)id
;
304 /* Return idx into hashtable for a string */
305 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
306 {val
= *str
+ (val
<< 6) + (val
<< 16) - val
; i
++; }
308 return (val
& HashSize(ht
));
311 ULONG
CalcHashStr_Org(struct HashTable
*ht
, IPTR id
)
313 STRPTR str
= (STRPTR
)id
;
315 /* Return idx into hashtable for a string */
316 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
317 {val
+= *str
; i
++; }
319 return (val
& HashSize(ht
));
322 ULONG
CalcHashStr(struct HashTable
*ht
, IPTR id
)
324 return CalcHashStr_KR(ht
, id
);
327 /* Prints contents of a hastable */
328 VOID
print_table(struct HashTable
*ht
, struct IntOOPBase
*OOPBase
)
333 for (idx
= 0; idx
< HashSize(ht
); idx
++)
337 D(bug("idx %ld: ", idx
));
338 for (b
= ht
->Table
[idx
]; b
; b
= b
->Next
)
342 if (ht
->Type
== HT_INTEGER
)
345 bug("%s(%ld) ", (STRPTR
)b
->ID
, ((struct iid_bucket
*)b
)->refcount
);
352 D(bug("HashTable fill ratio: %d %%\n", filled
* 100 / HashSize(ht
)));