7 struct hash
*hash_init(long (*datahash
) (void *data
),
8 long (*keyhash
) (void *data
),
9 int (*datacmp
) (void *data
, void *key
),
12 struct hash
*hash
= xmalloc(sizeof(struct hash
));
13 hash
->datahash
= datahash
;
14 hash
->keyhash
= keyhash
;
15 hash
->datacmp
= datacmp
;
18 hash
->table
= xmalloc(size
* sizeof(struct entry
*));
19 memset(hash
->table
, 0, size
* sizeof(struct entry
*));
23 long str_hash(void *p
)
28 x
= (1000003 * x
) ^ *s
++;
32 static long hash_key(struct hash
*hash
, long value
)
34 return (value
>= 0 ? value
: -value
) % hash
->size
;
37 static void hash_grow(struct hash
*hash
, int size
);
39 void hash_put(struct hash
*hash
, void *data
)
41 long i
= hash_key(hash
, hash
->datahash(data
));
42 struct entry
*newdata
= xmalloc(sizeof(struct entry
*));
46 newdata
->next
= hash
->table
[i
];
47 hash
->table
[i
] = newdata
;
48 if (hash
->collisions
> hash
->size
/ 2)
49 hash_grow(hash
, hash
->size
* 2);
52 void *hash_get(struct hash
*hash
, void *key
)
54 struct entry
*cur
= hash
->table
[hash_key(hash
, hash
->keyhash(key
))];
56 if (!hash
->datacmp(cur
->data
, key
))
63 static void entry_walk(struct hash
*hash
,
64 void (*callback
) (struct entry
*, void *data
),
68 for (i
= 0; i
< hash
->size
; i
++) {
69 struct entry
*cur
= hash
->table
[i
];
71 struct entry
*old
= cur
;
78 static void free_entry(struct entry
*entry
, void *data
)
83 void hash_release(struct hash
*hash
)
85 entry_walk(hash
, free_entry
, NULL
);
90 static void copy_and_free_entry(struct entry
*entry
, void *newhash
)
92 hash_put(newhash
, entry
->data
);
96 static void hash_grow(struct hash
*hash
, int size
)
98 struct hash
*newhash
= hash_init(hash
->datahash
, hash
->keyhash
,
100 entry_walk(hash
, copy_and_free_entry
, newhash
);
102 memcpy(hash
, newhash
, sizeof(*hash
));
107 void (*walk
)(void *data
, void *arg
) ;
111 static void call_entry(struct entry
*entry
, void *data
)
113 struct walk_data
*walk_data
= data
;
114 walk_data
->walk(entry
->data
, walk_data
->arg
);
117 void hash_walk(struct hash
*hash
,
118 void (*walk
)(void *data
, void *arg
),
121 struct walk_data walk_data
;
123 walk_data
.walk
= walk
;
124 entry_walk(hash
, call_entry
, &walk_data
);