1 /* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
3 /* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
8 #include "OnigurumaUefiPort.h"
17 typedef struct st_table_entry st_table_entry
;
19 struct st_table_entry
{
26 #define ST_DEFAULT_MAX_DENSITY 5
27 #define ST_DEFAULT_INIT_TABLE_SIZE 11
30 * DEFAULT_MAX_DENSITY is the default for the largest we allow the
31 * average number of items per bin before increasing the number of
34 * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
39 static int numcmp(long, long);
40 static int numhash(long);
41 static struct st_hash_type type_numhash
= {
46 /* extern int strcmp(const char *, const char *); */
47 static int strhash(const char *);
48 static struct st_hash_type type_strhash
= {
53 static void rehash(st_table
*);
55 #define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
56 #define Calloc(n,s) (char*)xcalloc((n),(s))
58 #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
60 #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
61 #define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
64 * MINSIZE is the minimum size of a dictionary.
70 Table of prime numbers 2^n+a, 2<=n<=30.
72 static const long primes
[] = {
111 for (i
=3; i
<31; i
++) {
112 if ((1<<i
) > size
) return 1<<i
;
118 for (i
= 0, newsize
= MINSIZE
;
119 i
< (int )(sizeof(primes
)/sizeof(primes
[0]));
122 if (newsize
> size
) return primes
[i
];
124 /* Ran out of polynomials */
125 return -1; /* should raise exception */
130 static int collision
= 0;
131 static int init_st
= 0;
136 FILE *f
= fopen("/tmp/col", "w");
137 fprintf(f
, "collision: %d\n", collision
);
143 st_init_table_with_size(type
, size
)
144 struct st_hash_type
*type
;
156 size
= new_size(size
); /* round up to prime number */
158 tbl
= alloc(st_table
);
159 CHECK_NULL_RETURN(tbl
);
161 tbl
->num_entries
= 0;
162 tbl
->num_bins
= size
;
163 tbl
->bins
= (st_table_entry
**)Calloc(size
, sizeof(st_table_entry
*));
170 struct st_hash_type
*type
;
172 return st_init_table_with_size(type
, 0);
176 st_init_numtable(void)
178 return st_init_table(&type_numhash
);
182 st_init_numtable_with_size(size
)
185 return st_init_table_with_size(&type_numhash
, size
);
189 st_init_strtable(void)
191 return st_init_table(&type_strhash
);
195 st_init_strtable_with_size(size
)
198 return st_init_table_with_size(&type_strhash
, size
);
205 register st_table_entry
*ptr
, *next
;
208 for(i
= 0; i
< table
->num_bins
; i
++) {
209 ptr
= table
->bins
[i
];
220 #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
221 ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
224 #define COLLISION collision++
229 #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
230 bin_pos = hash_val%(table)->num_bins;\
231 ptr = (table)->bins[bin_pos];\
232 if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
234 while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
242 st_lookup(table
, key
, value
)
244 register st_data_t key
;
247 unsigned int hash_val
, bin_pos
;
248 register st_table_entry
*ptr
;
250 hash_val
= do_hash(key
, table
);
251 FIND_ENTRY(table
, ptr
, hash_val
, bin_pos
);
257 if (value
!= 0) *value
= ptr
->record
;
262 #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
264 st_table_entry *entry;\
265 if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\
267 bin_pos = hash_val % table->num_bins;\
270 entry = alloc(st_table_entry);\
271 if (entry == NULL) {\
275 entry->hash = hash_val;\
277 entry->record = value;\
278 entry->next = table->bins[bin_pos];\
279 table->bins[bin_pos] = entry;\
280 table->num_entries++;\
284 st_insert(table
, key
, value
)
285 register st_table
*table
;
286 register st_data_t key
;
289 unsigned int hash_val
, bin_pos
;
290 register st_table_entry
*ptr
;
292 hash_val
= do_hash(key
, table
);
293 FIND_ENTRY(table
, ptr
, hash_val
, bin_pos
);
296 ADD_DIRECT(table
, key
, value
, hash_val
, bin_pos
);
306 st_add_direct(table
, key
, value
)
311 unsigned int hash_val
, bin_pos
;
313 hash_val
= do_hash(key
, table
);
314 bin_pos
= hash_val
% table
->num_bins
;
315 ADD_DIRECT(table
, key
, value
, hash_val
, bin_pos
);
320 register st_table
*table
;
322 register st_table_entry
*ptr
, *next
, **new_bins
;
323 int i
, old_num_bins
= table
->num_bins
, new_num_bins
;
324 unsigned int hash_val
;
326 new_num_bins
= new_size(old_num_bins
+1);
327 new_bins
= (st_table_entry
**)Calloc(new_num_bins
, sizeof(st_table_entry
*));
328 if (new_bins
== NULL
) {
332 for(i
= 0; i
< old_num_bins
; i
++) {
333 ptr
= table
->bins
[i
];
336 hash_val
= ptr
->hash
% new_num_bins
;
337 ptr
->next
= new_bins
[hash_val
];
338 new_bins
[hash_val
] = ptr
;
343 table
->num_bins
= new_num_bins
;
344 table
->bins
= new_bins
;
352 st_table_entry
*ptr
, *entry
;
353 int i
, num_bins
= old_table
->num_bins
;
355 new_table
= alloc(st_table
);
356 if (new_table
== 0) {
360 *new_table
= *old_table
;
361 new_table
->bins
= (st_table_entry
**)
362 Calloc((unsigned)num_bins
, sizeof(st_table_entry
*));
364 if (new_table
->bins
== 0) {
369 for(i
= 0; i
< num_bins
; i
++) {
370 new_table
->bins
[i
] = 0;
371 ptr
= old_table
->bins
[i
];
373 entry
= alloc(st_table_entry
);
375 free(new_table
->bins
);
380 entry
->next
= new_table
->bins
[i
];
381 new_table
->bins
[i
] = entry
;
389 st_delete(table
, key
, value
)
390 register st_table
*table
;
391 register st_data_t
*key
;
394 unsigned int hash_val
;
396 register st_table_entry
*ptr
;
398 hash_val
= do_hash_bin(*key
, table
);
399 ptr
= table
->bins
[hash_val
];
402 if (value
!= 0) *value
= 0;
406 if (EQUAL(table
, *key
, ptr
->key
)) {
407 table
->bins
[hash_val
] = ptr
->next
;
408 table
->num_entries
--;
409 if (value
!= 0) *value
= ptr
->record
;
415 for(; ptr
->next
!= 0; ptr
= ptr
->next
) {
416 if (EQUAL(table
, ptr
->next
->key
, *key
)) {
418 ptr
->next
= ptr
->next
->next
;
419 table
->num_entries
--;
420 if (value
!= 0) *value
= tmp
->record
;
431 st_delete_safe(table
, key
, value
, never
)
432 register st_table
*table
;
433 register st_data_t
*key
;
437 unsigned int hash_val
;
438 register st_table_entry
*ptr
;
440 hash_val
= do_hash_bin(*key
, table
);
441 ptr
= table
->bins
[hash_val
];
444 if (value
!= 0) *value
= 0;
448 for(; ptr
!= 0; ptr
= ptr
->next
) {
449 if ((ptr
->key
!= never
) && EQUAL(table
, ptr
->key
, *key
)) {
450 table
->num_entries
--;
452 if (value
!= 0) *value
= ptr
->record
;
453 ptr
->key
= ptr
->record
= never
;
462 #if defined(__GNUC__)
463 delete_never(st_data_t key
__attribute__ ((unused
)), st_data_t value
,
466 delete_never(key
, value
, never
)
467 st_data_t key
, value
, never
;
470 if (value
== never
) return ST_DELETE
;
475 st_cleanup_safe(table
, never
)
479 int num_entries
= table
->num_entries
;
481 st_foreach(table
, delete_never
, never
);
482 table
->num_entries
= num_entries
;
486 st_foreach(table
, func
, arg
)
491 st_table_entry
*ptr
, *last
, *tmp
;
492 enum st_retval retval
;
495 for(i
= 0; i
< table
->num_bins
; i
++) {
497 for(ptr
= table
->bins
[i
]; ptr
!= 0;) {
498 retval
= (*func
)(ptr
->key
, ptr
->record
, arg
);
500 case ST_CHECK
: /* check if hash is modified during iteration */
502 if (i
< table
->num_bins
) {
503 for (tmp
= table
->bins
[i
]; tmp
; tmp
=tmp
->next
) {
504 if (tmp
== ptr
) break;
508 /* call func with error notice */
521 table
->bins
[i
] = ptr
->next
;
524 last
->next
= ptr
->next
;
528 table
->num_entries
--;
537 register const char *string
;
542 register unsigned int h
= 0, g
;
544 while ((c
= *string
++) != '\0') {
546 if ( g
= h
& 0xF0000000 )
552 register int val
= 0;
554 while ((c
= *string
++) != '\0') {
562 return val
+ (val
<< 15);
564 register int val
= 0;
566 while ((c
= *string
++) != '\0') {
570 return val
+ (val
>>5);