diff options
Diffstat (limited to 'hashmap.c')
-rw-r--r-- | hashmap.c | 58 |
1 files changed, 37 insertions, 21 deletions
@@ -140,8 +140,8 @@ static inline struct hashmap_entry **find_entry_ptr(const struct hashmap *map, } static int always_equal(const void *unused_cmp_data, - const void *unused1, - const void *unused2, + const struct hashmap_entry *unused1, + const struct hashmap_entry *unused2, const void *unused_keydata) { return 0; @@ -171,41 +171,49 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, map->do_count_items = 1; } -void hashmap_free(struct hashmap *map, int free_entries) +void hashmap_free_(struct hashmap *map, ssize_t entry_offset) { if (!map || !map->table) return; - if (free_entries) { + if (entry_offset >= 0) { /* called by hashmap_free_entries */ struct hashmap_iter iter; struct hashmap_entry *e; + hashmap_iter_init(map, &iter); while ((e = hashmap_iter_next(&iter))) - free(e); + /* + * like container_of, but using caller-calculated + * offset (caller being hashmap_free_entries) + */ + free((char *)e - entry_offset); } free(map->table); memset(map, 0, sizeof(*map)); } -void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata) +struct hashmap_entry *hashmap_get(const struct hashmap *map, + const struct hashmap_entry *key, + const void *keydata) { return *find_entry_ptr(map, key, keydata); } -void *hashmap_get_next(const struct hashmap *map, const void *entry) +struct hashmap_entry *hashmap_get_next(const struct hashmap *map, + const struct hashmap_entry *entry) { - struct hashmap_entry *e = ((struct hashmap_entry *) entry)->next; + struct hashmap_entry *e = entry->next; for (; e; e = e->next) if (entry_equals(map, entry, e, NULL)) return e; return NULL; } -void hashmap_add(struct hashmap *map, void *entry) +void hashmap_add(struct hashmap *map, struct hashmap_entry *entry) { unsigned int b = bucket(map, entry); /* add entry */ - ((struct hashmap_entry *) entry)->next = map->table[b]; + entry->next = map->table[b]; map->table[b] = entry; /* fix size and rehash if appropriate */ @@ -216,7 +224,9 @@ void hashmap_add(struct hashmap *map, void *entry) } } -void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata) +struct hashmap_entry *hashmap_remove(struct hashmap *map, + const struct hashmap_entry *key, + const void *keydata) { struct hashmap_entry *old; struct hashmap_entry **e = find_entry_ptr(map, key, keydata); @@ -238,7 +248,8 @@ void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata) return old; } -void *hashmap_put(struct hashmap *map, void *entry) +struct hashmap_entry *hashmap_put(struct hashmap *map, + struct hashmap_entry *entry) { struct hashmap_entry *old = hashmap_remove(map, entry, NULL); hashmap_add(map, entry); @@ -252,7 +263,7 @@ void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter) iter->next = NULL; } -void *hashmap_iter_next(struct hashmap_iter *iter) +struct hashmap_entry *hashmap_iter_next(struct hashmap_iter *iter) { struct hashmap_entry *current = iter->next; for (;;) { @@ -275,10 +286,15 @@ struct pool_entry { }; static int pool_entry_cmp(const void *unused_cmp_data, - const struct pool_entry *e1, - const struct pool_entry *e2, - const unsigned char *keydata) + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, + const void *keydata) { + const struct pool_entry *e1, *e2; + + e1 = container_of(eptr, const struct pool_entry, ent); + e2 = container_of(entry_or_key, const struct pool_entry, ent); + return e1->data != keydata && (e1->len != e2->len || memcmp(e1->data, keydata, e1->len)); } @@ -290,18 +306,18 @@ const void *memintern(const void *data, size_t len) /* initialize string pool hashmap */ if (!map.tablesize) - hashmap_init(&map, (hashmap_cmp_fn) pool_entry_cmp, NULL, 0); + hashmap_init(&map, pool_entry_cmp, NULL, 0); /* lookup interned string in pool */ - hashmap_entry_init(&key, memhash(data, len)); + hashmap_entry_init(&key.ent, memhash(data, len)); key.len = len; - e = hashmap_get(&map, &key, data); + e = hashmap_get_entry(&map, &key, ent, data); if (!e) { /* not found: create it */ FLEX_ALLOC_MEM(e, data, data, len); - hashmap_entry_init(e, key.ent.hash); + hashmap_entry_init(&e->ent, key.ent.hash); e->len = len; - hashmap_add(&map, e); + hashmap_add(&map, &e->ent); } return e->data; } |