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>
14 #include <libraries/uuid.h>
21 #include <aros/debug.h>
25 #define UB(x) ((UBYTE *)x)
31 /* Allocates a hashtable for given number of entries,
32 ** so that hash table is no more than 50% full.
33 ** Initializes table as empty.
36 struct HashTable
*NewHash(ULONG entries
, UBYTE type
, struct IntOOPBase
*OOPBase
)
45 EnterFunc(bug("NewHash(entries=%ld, type=%ld)\n", entries
, type
));
47 /* Allocate hashtable struct */
50 ht
= AllocMem(sizeof (struct HashTable
), MEMF_ANY
);
53 /* Allocate table of size 2^n - 1 */
54 /* Find the highest bit in 'initial' */
55 for (i
= 31; i
>= 0; i
--)
57 if ((temp
<< i
) & entries
)
63 /* Make sure table is never more than 50% full */
66 entries
= (temp
<< i
);
67 entries
--; /* 2^n - 1 */
70 size
= UB( &ht
[entries
] ) - UB( &ht
[0] );
72 /* Allocate the table */
73 ht
->Table
= AllocVec(size
, MEMF_ANY
|MEMF_CLEAR
);
76 ht
->HashMask
= entries
- 1;
79 /* Initialize the hashtable's Lookup and CalcHash
80 ** accordint to if we want to hash integers or strings
85 ht
->Lookup
= HashLookupULONG
;
86 ht
->CalcHash
= CalcHashULONG
;
90 ht
->Lookup
= HashLookupStr
;
91 ht
->CalcHash
= CalcHashStr
;
95 ht
->Lookup
= HashLookupUUID
;
96 ht
->CalcHash
= CalcHashUUID
;
101 ReturnPtr ("NewHash", struct HashTable
*, ht
);
103 FreeMem(ht
, sizeof (struct HashTable
));
105 ReturnPtr ("NewHash", struct HashTable
*, NULL
);
111 VOID
FreeHash(struct HashTable
*ht
, VOID (*freebucket
)(), struct IntOOPBase
*OOPBase
)
115 EnterFunc(bug("FreeHash(ht=%p, freebucket=%p)\n", ht
, freebucket
));
117 D(bug("Hashsize: %ld\n", HashSize(ht
) ));
120 /* Free all buckets */
121 for (i
= 0; i
< HashSize(ht
); i
++)
123 struct Bucket
*b
, *next_b
;
124 D(bug("Freeing buckets at entry %ld\n", i
));
126 for (b
= ht
->Table
[i
]; b
; b
= next_b
)
129 /* USe usersupplied func to free bucket */
130 freebucket(b
, OOPBase
);
135 /* Free the hashtable struct */
136 FreeMem(ht
, sizeof (struct HashTable
));
138 ReturnVoid("FreeHash");
144 struct Bucket
*HashLookupULONG(struct HashTable
*ht
, IPTR id
, struct IntOOPBase
*OOPBase
)
147 EnterFunc(bug("HashLookupULONG(ht=%p, id=%ld)\n", ht
, id
));
148 /* Function for looking up integers in the table */
149 for (b
= ht
->Table
[CalcHashULONG(ht
, id
)]; b
; b
= b
->Next
)
151 D(bug("Current bucket: %p of id %ld\n", b
, b
->ID
));
153 ReturnPtr ("HashLookupULONG", struct Bucket
*, b
);
156 ReturnPtr ("HashLookupULONG", struct Bucket
*, NULL
);
159 struct Bucket
*HashLookupUUID(struct HashTable
*ht
, IPTR id
, struct IntOOPBase
*OOPBase
)
162 EnterFunc(uuid_t uuid
= *(uuid_t
*)id
);
164 EnterFunc(bug("HashLookupUUID(ht=%p, id={%04lx-%02lx-%02lx-%02x%02x-%02x%02x%02x%02x%02x%02x})\n", ht
,
165 uuid
.time_low
, uuid
.time_mid
, uuid
.time_hi_and_version
,
166 uuid
.clock_seq_hi_and_reserved
, uuid
.clock_seq_low
,
167 uuid
.node
[5], uuid
.node
[4], uuid
.node
[3], uuid
.node
[2], uuid
.node
[1], uuid
.node
[0]));
169 /* Function for looking up integers in the table */
170 for (b
= ht
->Table
[CalcHashUUID(ht
, id
)]; b
; b
= b
->Next
)
172 D(bug("Current bucket: %p of id %p\n", b
, b
->ID
));
174 ReturnPtr ("HashLookupUUID", struct Bucket
*, b
);
177 ReturnPtr ("HashLookupUUID", struct Bucket
*, NULL
);
180 struct Bucket
*HashLookupStr(struct HashTable
*ht
, IPTR id
, struct IntOOPBase
*OOPBase
)
184 /* Function for looking up strings in the table */
185 EnterFunc(bug("HashLookupStr(ht=%p, id=%s)\n", ht
, (STRPTR
)id
));
186 for (b
= ht
->Table
[CalcHashStr(ht
, id
)]; b
; b
= b
->Next
)
188 D(bug("Bucket: %p\n", b
));
189 D(bug("ID: %p\n", b
->ID
));
190 D(bug("ID: %s\n", b
->ID
));
191 if (!strcmp((STRPTR
)b
->ID
, (STRPTR
)id
))
192 ReturnPtr ("HashLookupStr", struct Bucket
*, b
);
194 ReturnPtr ("HashLookupStr", struct Bucket
*, NULL
);
200 BOOL
CopyHash(struct HashTable
*dest_ht
201 ,struct HashTable
*src_ht
202 ,struct Bucket
* (*copybucket
)()
204 ,struct IntOOPBase
*OOPBase
)
208 /* Copies all buckets of src_ht into dest_ht */
210 EnterFunc(bug("CopyHash(dest_ht=%p, src_ht=%p, copybucket=%p,data = %p)\n",
211 dest_ht
, src_ht
, copybucket
, data
));
213 /* for each entry in the table */
214 for (i
= 0; i
< HashSize(src_ht
); i
++ )
218 D(bug("idx: %ld\n", i
));
220 /* for each bucket at curent entry */
221 for (b
= src_ht
->Table
[i
]; b
; b
= b
->Next
)
223 /* Rehash bucket into destination hashtable */
224 struct Bucket
*new_b
;
226 D(bug("Bucket: %p\n", b
));
228 /* use user-supllied func to copy the bucket */
229 new_b
= copybucket(b
, data
, OOPBase
);
231 ReturnBool ("CopyHash", FALSE
);
233 /* insert the new bucket into detsination table */
234 InsertBucket(dest_ht
, new_b
, OOPBase
);
237 } /* For each bucket at current entry */
239 } /* For each entry in source hashtable */
241 ReturnBool ("CopyHash", TRUE
);
244 /*********************
246 *********************/
247 VOID
InsertBucket(struct HashTable
*ht
, struct Bucket
*b
, struct IntOOPBase
*OOPBase
)
249 /* Inserts bucket into hashtable according to its ID */
252 EnterFunc(bug("InsertBucket(ht=%p, b=%p)\n", ht
, b
));
254 idx
= ht
->CalcHash(ht
, b
->ID
);
255 b
->Next
= ht
->Table
[idx
];
257 D(bug("b->Next=%p\n", b
->Next
));
259 ReturnVoid ("InsertBucket");
263 VOID
RemoveBucket(struct HashTable
*ht
, struct Bucket
*b
)
266 struct Bucket
*last_b
= NULL
,
268 idx
= ht
->CalcHash(ht
, b
->ID
);
270 /* Search for bucket to remove */
271 for (cur_b
= ht
->Table
[idx
]; cur_b
; cur_b
= cur_b
->Next
)
278 /* Remove bucket from chain */
279 last_b
->Next
= cur_b
->Next
;
281 /* Not really neccessar, but ... */
286 /* We are removing the first bucket */
287 ht
->Table
[idx
] = cur_b
->Next
;
293 } /* for (each bucket at idx) */
297 ULONG
CalcHashULONG(struct HashTable
*ht
, IPTR id
)
299 /* Return idx into hashtable for an integer */
300 return (id
% HashMask(ht
));
303 ULONG
CalcHashUUID(struct HashTable
*ht
, IPTR id
)
311 uuid
.uuid
= *(uuid_t
*)id
;
318 return (val
& HashSize(ht
));
321 static ULONG
CalcHashStr_KR(struct HashTable
*ht
, IPTR id
)
323 STRPTR str
= (STRPTR
)id
;
325 /* Return idx into hashtable for a string */
326 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
327 {val
+= *str
; i
++; }
329 return (val
& HashSize(ht
));
333 static ULONG
CalcHashStr_DJB2(struct HashTable
*ht
, IPTR id
)
335 STRPTR str
= (STRPTR
)id
;
337 /* Return idx into hashtable for a string */
338 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
339 {val
= ((val
<< 5) + val
) ^ *str
; i
++; }
341 return (val
& HashSize(ht
));
345 ULONG
CalcHashStr_SDBM(struct HashTable
*ht
, IPTR id
)
347 STRPTR str
= (STRPTR
)id
;
349 /* Return idx into hashtable for a string */
350 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
351 {val
= *str
+ (val
<< 6) + (val
<< 16) - val
; i
++; }
353 return (val
& HashSize(ht
));
356 ULONG
CalcHashStr_Org(struct HashTable
*ht
, IPTR id
)
358 STRPTR str
= (STRPTR
)id
;
360 /* Return idx into hashtable for a string */
361 for (i
= 0, val
= 0; (i
< MAX_HASH_CHARS
) && *str
; str
++)
362 {val
+= *str
; i
++; }
364 return (val
& HashSize(ht
));
367 ULONG
CalcHashStr(struct HashTable
*ht
, IPTR id
)
369 return CalcHashStr_KR(ht
, id
);
372 /* Prints contents of a hastable */
373 VOID
print_table(struct HashTable
*ht
, struct IntOOPBase
*OOPBase
)
378 for (idx
= 0; idx
< HashSize(ht
); idx
++)
382 D(bug("idx %ld: ", idx
));
383 for (b
= ht
->Table
[idx
]; b
; b
= b
->Next
)
387 if (ht
->Type
== HT_INTEGER
)
390 bug("%s(%ld) ", (STRPTR
)b
->ID
, ((struct iid_bucket
*)b
)->refcount
);
397 D(bug("HashTable fill ratio: %d %%\n", filled
* 100 / HashSize(ht
)));