5 #define hash_func(k) sdbm((unsigned char *)k)
6 #define hash_func2(k1, k2) (hash_func(k1) ^ hash_func(k2))
8 typedef struct hash_bucket
{
12 struct hash_bucket
*next
;
16 hash_bucket
**buckets
;
17 unsigned int num_buckets
;
18 unsigned int added
, removed
;
20 unsigned int max_entries
;
23 /* struct data access functions */
24 unsigned int hash_entries(hash_table
*table
)
26 return table
? table
->entries
: 0;
29 unsigned int hash_entries_max(hash_table
*table
)
31 return table
? table
->max_entries
: 0;
34 unsigned int hash_entries_added(hash_table
*table
)
36 return table
? table
->added
: 0;
39 unsigned int hash_entries_removed(hash_table
*table
)
41 return table
? table
->removed
: 0;
44 unsigned int hash_table_size(hash_table
*table
)
46 return table
? table
->num_buckets
: 0;
49 void hash_debug_print_table_data(hash_table
*table
, const char *name
, int force
)
51 int delta
= hash_check_table(table
);
56 count
= hash_count_entries(table
);
57 printf("debug data for hash table '%s'\n", name
);
58 printf(" entries: %u; counted: %u; delta: %d\n",
59 table
->entries
, count
, delta
);
60 printf(" added: %u; removed: %u; delta: %d\n",
61 table
->added
, table
->removed
, table
->added
- table
->removed
);
65 * polynomial conversion ignoring overflows
67 * Ozan Yigit's original sdbm algorithm, but without Duff's device
68 * so we can use it without knowing the length of the string
70 static inline unsigned int sdbm(const unsigned register char *k
)
72 register unsigned int h
= 0;
80 static inline int hash_add_bucket(hash_table
*table
, const char *k1
, const char *k2
, void *data
, unsigned int h
)
84 if (!(bkt
= malloc(sizeof(*bkt
))))
87 h
= h
% table
->num_buckets
;
93 bkt
->next
= table
->buckets
[h
];
94 table
->buckets
[h
] = bkt
;
96 if (++table
->entries
> table
->max_entries
)
97 table
->max_entries
= table
->entries
;
102 int hash_add2(hash_table
*table
, const char *k1
, const char *k2
, void *data
)
104 return hash_add_bucket(table
, k1
, k2
, data
, hash_func2(k1
, k2
));
107 int hash_add(hash_table
*table
, const char *key
, void *data
)
109 return hash_add_bucket(table
, key
, NULL
, data
, hash_func(key
));
112 static hash_bucket
*hash_get_bucket(hash_table
*table
, const char *key
)
119 bkt
= table
->buckets
[hash_func(key
) % table
->num_buckets
];
120 for (; bkt
; bkt
= bkt
->next
) {
121 if (!strcmp(key
, bkt
->key
))
128 static hash_bucket
*hash_get_bucket2(hash_table
*table
, const char *k1
, const char *k2
)
135 bkt
= table
->buckets
[hash_func2(k1
, k2
) % table
->num_buckets
];
136 for (; bkt
; bkt
= bkt
->next
) {
137 if (!strcmp(k1
, bkt
->key
) && !strcmp(k2
, bkt
->key2
))
144 void *hash_find(hash_table
*table
, const char *key
)
148 bkt
= hash_get_bucket(table
, key
);
150 return bkt
? bkt
->data
: NULL
;
153 void *hash_find2(hash_table
*table
, const char *k1
, const char *k2
)
157 bkt
= hash_get_bucket2(table
, k1
, k2
);
159 return bkt
? bkt
->data
: NULL
;
162 hash_table
*hash_init(unsigned int buckets
)
164 hash_table
*table
= calloc(sizeof(hash_table
), 1);
167 table
->buckets
= calloc(buckets
, sizeof(hash_bucket
*));
168 if (table
->buckets
) {
169 table
->num_buckets
= buckets
;
179 void *hash_update(hash_table
*table
, const char *key
, void *data
)
184 bkt
= hash_get_bucket(table
, key
);
186 hash_add(table
, key
, data
);
190 current_data
= bkt
->data
;
195 void *hash_update2(hash_table
*table
, const char *key
, const char *key2
, void *data
)
199 bkt
= hash_get_bucket2(table
, key
, key2
);
201 hash_add2(table
, key
, key2
, data
);
209 static inline void *hash_destroy_bucket(hash_bucket
*bkt
)
218 void *hash_remove(hash_table
*table
, const char *key
)
221 hash_bucket
*bkt
, *prev
;
223 h
= hash_func(key
) % table
->num_buckets
;
225 if (!(bkt
= table
->buckets
[h
]))
228 if (!strcmp(key
, bkt
->key
)) {
229 table
->buckets
[h
] = bkt
->next
;
232 return hash_destroy_bucket(bkt
);
236 for (bkt
= bkt
->next
; bkt
; bkt
= bkt
->next
) {
237 if (!strcmp(key
, bkt
->key
)) {
238 prev
->next
= bkt
->next
;
241 return hash_destroy_bucket(bkt
);
248 void *hash_remove2(hash_table
*table
, const char *k1
, const char *k2
)
251 hash_bucket
*bkt
, *prev
;
253 h
= hash_func2(k1
, k2
) % table
->num_buckets
;
255 if (!(bkt
= table
->buckets
[h
]))
258 if (!strcmp(k1
, bkt
->key
) && !strcmp(k2
, bkt
->key2
)) {
259 table
->buckets
[h
] = bkt
->next
;
262 return hash_destroy_bucket(bkt
);
266 for (bkt
= bkt
->next
; bkt
; bkt
= bkt
->next
) {
267 if (!strcmp(k1
, bkt
->key
) && !strcmp(k2
, bkt
->key2
)) {
268 prev
->next
= bkt
->next
;
271 return hash_destroy_bucket(bkt
);
278 unsigned int hash_count_entries(hash_table
*table
)
281 unsigned int count
= 0;
283 for (i
= 0; i
< table
->num_buckets
; i
++) {
285 for (bkt
= table
->buckets
[i
]; bkt
; bkt
= bkt
->next
)
292 int hash_check_table(hash_table
*table
)
294 return table
? table
->entries
- hash_count_entries(table
) : 0;
297 void hash_walk_data(hash_table
*table
, int (*walker
)(void *))
299 hash_bucket
*bkt
, *prev
;
305 for (i
= 0; i
< table
->num_buckets
; i
++) {
308 prev
= table
->buckets
[i
];
310 for (bkt
= table
->buckets
[i
]; bkt
; bkt
= next
) {
313 if (walker(bkt
->data
) != HASH_WALK_REMOVE
) {
314 /* only update prev if we don't remove current */
321 hash_destroy_bucket(bkt
);
324 table
->buckets
[i
] = next
;
330 /* inserts a guaranteed unique entry to the hash-table */
331 int hash_add_unique(hash_table
*table
, const char *key
, void *data
)
336 h
= hash_func(key
) % table
->num_buckets
;
337 for (bkt
= table
->buckets
[h
]; bkt
; bkt
= bkt
->next
)
338 if (!strcmp(bkt
->key
, key
))
341 /* it's a unique key */
342 return hash_add_bucket(table
, key
, NULL
, data
, h
);
345 int hash_add_unique2(hash_table
*table
, const char *k1
, const char *k2
, void *data
)
350 h
= hash_func2(k1
, k2
) % table
->num_buckets
;
351 for (bkt
= table
->buckets
[h
]; bkt
; bkt
= bkt
->next
)
352 if (!strcmp(bkt
->key
, k1
) && !strcmp(bkt
->key2
, k2
))
355 return hash_add_bucket(table
, k1
, k2
, data
, h
);