2
/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
7
* Implementation of the hash table type.
14
hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
15
const hashtab_key_t key),
16
int (*keycmp) (hashtab_t h,
17
const hashtab_key_t key1,
18
const hashtab_key_t key2),
25
p = (hashtab_t) malloc(sizeof(hashtab_val_t));
29
memset(p, 0, sizeof(hashtab_val_t));
32
p->hash_value = hash_value;
34
p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size);
35
if (p->htable == NULL) {
39
for (i = 0; i < size; i++)
40
p->htable[i] = (hashtab_ptr_t) NULL;
45
int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
48
hashtab_ptr_t prev, cur, newnode;
51
return HASHTAB_OVERFLOW;
53
hvalue = h->hash_value(h, key);
55
cur = h->htable[hvalue];
56
while (cur && h->keycmp(h, key, cur->key) > 0) {
61
if (cur && (h->keycmp(h, key, cur->key) == 0))
62
return HASHTAB_PRESENT;
64
newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
66
return HASHTAB_OVERFLOW;
67
memset(newnode, 0, sizeof(struct hashtab_node));
69
newnode->datum = datum;
71
newnode->next = prev->next;
74
newnode->next = h->htable[hvalue];
75
h->htable[hvalue] = newnode;
79
return HASHTAB_SUCCESS;
82
int hashtab_remove(hashtab_t h, hashtab_key_t key,
83
void (*destroy) (hashtab_key_t k,
84
hashtab_datum_t d, void *args), void *args)
87
hashtab_ptr_t cur, last;
90
return HASHTAB_MISSING;
92
hvalue = h->hash_value(h, key);
94
cur = h->htable[hvalue];
95
while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
100
if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
101
return HASHTAB_MISSING;
104
h->htable[hvalue] = cur->next;
106
last->next = cur->next;
109
destroy(cur->key, cur->datum, args);
112
return HASHTAB_SUCCESS;
115
int hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum,
116
void (*destroy) (hashtab_key_t k,
117
hashtab_datum_t d, void *args), void *args)
120
hashtab_ptr_t prev, cur, newnode;
123
return HASHTAB_OVERFLOW;
125
hvalue = h->hash_value(h, key);
127
cur = h->htable[hvalue];
128
while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
133
if (cur && (h->keycmp(h, key, cur->key) == 0)) {
135
destroy(cur->key, cur->datum, args);
139
newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
141
return HASHTAB_OVERFLOW;
142
memset(newnode, 0, sizeof(struct hashtab_node));
144
newnode->datum = datum;
146
newnode->next = prev->next;
147
prev->next = newnode;
149
newnode->next = h->htable[hvalue];
150
h->htable[hvalue] = newnode;
154
return HASHTAB_SUCCESS;
157
hashtab_datum_t hashtab_search(hashtab_t h, const hashtab_key_t key)
166
hvalue = h->hash_value(h, key);
167
cur = h->htable[hvalue];
168
while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
171
if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
177
void hashtab_destroy(hashtab_t h)
180
hashtab_ptr_t cur, temp;
185
for (i = 0; i < h->size; i++) {
187
while (cur != NULL) {
201
int hashtab_map(hashtab_t h,
202
int (*apply) (hashtab_key_t k,
203
hashtab_datum_t d, void *args), void *args)
209
return HASHTAB_SUCCESS;
211
for (i = 0; i < h->size; i++) {
213
while (cur != NULL) {
214
ret = apply(cur->key, cur->datum, args);
220
return HASHTAB_SUCCESS;
223
void hashtab_map_remove_on_error(hashtab_t h,
224
int (*apply) (hashtab_key_t k,
227
void (*destroy) (hashtab_key_t k,
229
void *args), void *args)
233
hashtab_ptr_t last, cur, temp;
238
for (i = 0; i < h->size; i++) {
241
while (cur != NULL) {
242
ret = apply(cur->key, cur->datum, args);
245
last->next = cur->next;
247
h->htable[i] = cur->next;
253
destroy(temp->key, temp->datum, args);
266
void hashtab_hash_eval(hashtab_t h, char *tag)
269
int chain_len, slots_used, max_chain_len;
274
for (i = 0; i < h->size; i++) {
284
if (chain_len > max_chain_len)
285
max_chain_len = chain_len;
290
("%s: %d entries and %d/%d buckets used, longest chain length %d\n",
291
tag, h->nel, slots_used, h->size, max_chain_len);