diff options
author | Lennart Poettering <lennart@poettering.net> | 2006-06-19 21:53:48 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2006-06-19 21:53:48 +0000 |
commit | f44ba092651aa75055e109e04b4164ea92ae7fdc (patch) | |
tree | 5dfe076191b32946e78edf64d584d0a65f320013 /src/pulsecore/hashmap.c | |
parent | dd21f11deda64e65a6f75817496534c2c9dda1a8 (diff) |
big s/polyp/pulse/g
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1033 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/pulsecore/hashmap.c')
-rw-r--r-- | src/pulsecore/hashmap.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c new file mode 100644 index 000000000..2cddba1d5 --- /dev/null +++ b/src/pulsecore/hashmap.c @@ -0,0 +1,196 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <assert.h> +#include <string.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/idxset.h> +#include <pulsecore/log.h> + +#include "hashmap.h" + +#define BUCKETS 1023 + +struct hashmap_entry { + struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous; + unsigned hash; + const void *key; + void *value; +}; + +struct pa_hashmap { + unsigned size; + struct hashmap_entry **data; + struct hashmap_entry *first_entry; + + unsigned n_entries; + unsigned (*hash_func) (const void *p); + int (*compare_func) (const void*a, const void*b); +}; + +pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + pa_hashmap *h; + h = pa_xmalloc(sizeof(pa_hashmap)); + h->data = pa_xmalloc0(sizeof(struct hashmap_entry*)*(h->size = BUCKETS)); + h->first_entry = NULL; + h->n_entries = 0; + h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; + h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; + return h; +} + +static void remove(pa_hashmap *h, struct hashmap_entry *e) { + assert(e); + + if (e->next) + e->next->previous = e->previous; + if (e->previous) + e->previous->next = e->next; + else + h->first_entry = e->next; + + if (e->bucket_next) + e->bucket_next->bucket_previous = e->bucket_previous; + if (e->bucket_previous) + e->bucket_previous->bucket_next = e->bucket_next; + else { + assert(e->hash < h->size); + h->data[e->hash] = e->bucket_next; + } + + pa_xfree(e); + h->n_entries--; +} + +void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) { + assert(h); + + while (h->first_entry) { + if (free_func) + free_func(h->first_entry->value, userdata); + remove(h, h->first_entry); + } + + pa_xfree(h->data); + pa_xfree(h); +} + +static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) { + struct hashmap_entry *e; + assert(h && hash < h->size); + + for (e = h->data[hash]; e; e = e->bucket_next) + if (h->compare_func(e->key, key) == 0) + return e; + + return NULL; +} + +int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { + struct hashmap_entry *e; + unsigned hash; + assert(h); + + hash = h->hash_func(key) % h->size; + + if ((e = get(h, hash, key))) + return -1; + + e = pa_xmalloc(sizeof(struct hashmap_entry)); + e->hash = hash; + e->key = key; + e->value = value; + + e->previous = NULL; + e->next = h->first_entry; + if (h->first_entry) + h->first_entry->previous = e; + h->first_entry = e; + + e->bucket_previous = NULL; + e->bucket_next = h->data[hash]; + if (h->data[hash]) + h->data[hash]->bucket_previous = e; + h->data[hash] = e; + + h->n_entries ++; + return 0; +} + +void* pa_hashmap_get(pa_hashmap *h, const void *key) { + unsigned hash; + struct hashmap_entry *e; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if (!(e = get(h, hash, key))) + return NULL; + + return e->value; +} + +void* pa_hashmap_remove(pa_hashmap *h, const void *key) { + struct hashmap_entry *e; + unsigned hash; + void *data; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if (!(e = get(h, hash, key))) + return NULL; + + data = e->value; + remove(h, e); + return data; +} + +unsigned pa_hashmap_size(pa_hashmap *h) { + return h->n_entries; +} + +void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { + assert(h && state); + + if (!*state) + *state = h->first_entry; + else + *state = ((struct hashmap_entry*) *state)->next; + + if (!*state) { + if (key) + *key = NULL; + return NULL; + } + + if (key) + *key = ((struct hashmap_entry*) *state)->key; + + return ((struct hashmap_entry*) *state)->value; +} |