hashmap.c revision 729e3769c32242bbba26ea96900be005d52ce438
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/***
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel This file is part of systemd.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel Copyright 2010 Lennart Poettering
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel systemd is free software; you can redistribute it and/or modify it
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel under the terms of the GNU General Public License as published by
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel the Free Software Foundation; either version 2 of the License, or
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (at your option) any later version.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel systemd is distributed in the hope that it will be useful, but
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel WITHOUT ANY WARRANTY; without even the implied warranty of
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel General Public License for more details.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel You should have received a copy of the GNU General Public License
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel along with systemd; If not, see <http://www.gnu.org/licenses/>.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel***/
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <assert.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <stdlib.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <string.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <errno.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include "util.h"
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include "hashmap.h"
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include "macro.h"
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#define NBUCKETS 127
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstruct hashmap_entry {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel const void *key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel void *value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *bucket_next, *bucket_previous;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *iterate_next, *iterate_previous;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel};
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstruct Hashmap {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash_func_t hash_func;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel compare_func_t compare_func;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *iterate_list_head, *iterate_list_tail;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned n_entries;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel};
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#define BY_HASH(h) ((struct hashmap_entry**) ((uint8_t*) (h) + ALIGN(sizeof(Hashmap))))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelunsigned string_hash_func(const void *p) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel const char *c;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel for (c = p; *c; c++)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = 31 * hash + (unsigned) *c;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint string_compare_func(const void *a, const void *b) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return strcmp(a, b);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelunsigned trivial_hash_func(const void *p) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return PTR_TO_UINT(p);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint trivial_compare_func(const void *a, const void *b) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return a < b ? -1 : (a > b ? 1 : 0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan FriedelHashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel Hashmap *h;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(h = malloc0(ALIGN(sizeof(Hashmap)) + NBUCKETS * ALIGN(sizeof(struct hashmap_entry*)))))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->hash_func = hash_func ? hash_func : trivial_hash_func;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->compare_func = compare_func ? compare_func : trivial_compare_func;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->n_entries = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->iterate_list_head = h->iterate_list_tail = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return h;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(*h = hashmap_new(hash_func, compare_func)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOMEM;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void link_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(e);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* Insert into hash table */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->bucket_next = BY_HASH(h)[hash];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->bucket_previous = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (BY_HASH(h)[hash])
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel BY_HASH(h)[hash]->bucket_previous = e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel BY_HASH(h)[hash] = e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* Insert into iteration list */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->iterate_previous = h->iterate_list_tail;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->iterate_next = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (h->iterate_list_tail) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h->iterate_list_head);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->iterate_list_tail->iterate_next = e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(!h->iterate_list_head);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->iterate_list_head = e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->iterate_list_tail = e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->n_entries++;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h->n_entries >= 1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void unlink_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(e);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* Remove from iteration list */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->iterate_next)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->iterate_next->iterate_previous = e->iterate_previous;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel else
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->iterate_list_tail = e->iterate_previous;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->iterate_previous)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->iterate_previous->iterate_next = e->iterate_next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel else
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->iterate_list_head = e->iterate_next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* Remove from hash table bucket list */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->bucket_next)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->bucket_next->bucket_previous = e->bucket_previous;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->bucket_previous)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->bucket_previous->bucket_next = e->bucket_next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel else
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel BY_HASH(h)[hash] = e->bucket_next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h->n_entries >= 1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h->n_entries--;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void remove_entry(Hashmap *h, struct hashmap_entry *e) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(e);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(e->key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unlink_entry(h, e, hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(e);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid hashmap_free(Hashmap*h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hashmap_clear(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid hashmap_free_free(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel void *p;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while ((p = hashmap_steal_first(h)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(p);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hashmap_free(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid hashmap_clear(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (h->iterate_list_head)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel remove_entry(h, h->iterate_list_head);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(hash < NBUCKETS);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel for (e = BY_HASH(h)[hash]; e; e = e->bucket_next)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (h->compare_func(e->key, key) == 0)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_put(Hashmap *h, const void *key, void *value) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((e = hash_scan(h, hash, key))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->value == value)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -EEXIST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = new(struct hashmap_entry, 1)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOMEM;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->key = key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->value = value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel link_entry(h, e, hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_replace(Hashmap *h, const void *key, void *value) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((e = hash_scan(h, hash, key))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->key = key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->value = value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return hashmap_put(h, key, value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_get(Hashmap *h, const void *key) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(h, hash, key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return e->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_remove(Hashmap *h, const void *key) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel void *data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(h, hash, key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel data = e->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel remove_entry(h, e);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned old_hash, new_hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOENT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel old_hash = h->hash_func(old_key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(h, old_hash, old_key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOENT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel new_hash = h->hash_func(new_key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (hash_scan(h, new_hash, new_key))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -EEXIST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unlink_entry(h, e, old_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->key = new_key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->value = value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel link_entry(h, e, new_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e, *k;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned old_hash, new_hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOENT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel old_hash = h->hash_func(old_key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(h, old_hash, old_key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOENT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel new_hash = h->hash_func(new_key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((k = hash_scan(h, new_hash, new_key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e != k)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel remove_entry(h, k);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unlink_entry(h, e, old_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->key = new_key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e->value = value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel link_entry(h, e, new_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_remove_value(Hashmap *h, const void *key, void *value) {
bf515db2f8b506f788f69875fa1319cfbf177c9dJan Friedel struct hashmap_entry *e;
bf515db2f8b506f788f69875fa1319cfbf177c9dJan Friedel unsigned hash;
c7bef3b16d3d2a0b09ff75fbbd724283ef1ee7e7Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(h, hash, key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->value != value)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel remove_entry(h, e);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(i);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto at_end;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*i == ITERATOR_LAST)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto at_end;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*i == ITERATOR_FIRST && !h->iterate_list_head)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto at_end;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e = *i == ITERATOR_FIRST ? h->iterate_list_head : (struct hashmap_entry*) *i;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->iterate_next)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = (Iterator) e->iterate_next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel else
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = ITERATOR_LAST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (key)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *key = e->key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return e->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelat_end:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = ITERATOR_LAST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (key)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *key = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(i);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto at_beginning;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*i == ITERATOR_FIRST)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto at_beginning;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*i == ITERATOR_LAST && !h->iterate_list_tail)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto at_beginning;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel e = *i == ITERATOR_LAST ? h->iterate_list_tail : (struct hashmap_entry*) *i;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (e->iterate_previous)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = (Iterator) e->iterate_previous;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel else
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = ITERATOR_FIRST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (key)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *key = e->key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return e->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelat_beginning:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = ITERATOR_FIRST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (key)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *key = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(h, hash, key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *i = (Iterator) e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return e->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_first(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h->iterate_list_head)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return h->iterate_list_head->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_last(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h->iterate_list_tail)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return h->iterate_list_tail->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_steal_first(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel void *data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h->iterate_list_head)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel data = h->iterate_list_head->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel remove_entry(h, h->iterate_list_head);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid* hashmap_steal_first_key(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel void *key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h->iterate_list_head)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel key = (void*) h->iterate_list_head->key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel remove_entry(h, h->iterate_list_head);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return key;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelunsigned hashmap_size(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return h->n_entries;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelbool hashmap_isempty(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!h)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return true;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return h->n_entries == 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_merge(Hashmap *h, Hashmap *other) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!other)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel for (e = other->iterate_list_head; e; e = e->iterate_next) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int r;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((r = hashmap_put(h, e->key, e->value)) < 0)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (r != -EEXIST)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return r;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid hashmap_move(Hashmap *h, Hashmap *other) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e, *n;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* The same as hashmap_merge(), but every new item from other
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * is moved to h. This function is guaranteed to succeed. */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!other)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel for (e = other->iterate_list_head; e; e = n) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned h_hash, other_hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel n = e->iterate_next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h_hash = h->hash_func(e->key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (hash_scan(h, h_hash, e->key))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel other_hash = other->hash_func(e->key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unlink_entry(other, e, other_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel link_entry(h, e, h_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unsigned h_hash, other_hash;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct hashmap_entry *e;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!other)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel h_hash = h->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (hash_scan(h, h_hash, key))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -EEXIST;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel other_hash = other->hash_func(key) % NBUCKETS;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(e = hash_scan(other, other_hash, key)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return -ENOENT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel unlink_entry(other, e, other_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel link_entry(h, e, h_hash);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan FriedelHashmap *hashmap_copy(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel Hashmap *copy;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel assert(h);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(copy = hashmap_new(h->hash_func, h->compare_func)))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (hashmap_merge(copy, h) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel hashmap_free(copy);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return copy;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelchar **hashmap_get_strv(Hashmap *h) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel char **sv;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel Iterator it;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel char *item;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int n;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sv = new(char*, h->n_entries+1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!sv)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel n = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel HASHMAP_FOREACH(item, h, it)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sv[n++] = item;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sv[n] = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return sv;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel