4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include <pulse/xmalloc.h>
32 #include <pulsecore/idxset.h>
33 #include <pulsecore/log.h>
39 struct hashmap_entry {
40 struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous;
48 struct hashmap_entry **data;
49 struct hashmap_entry *first_entry;
52 pa_hash_func_t hash_func;
53 pa_compare_func_t compare_func;
56 pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
59 h = pa_xnew(pa_hashmap, 1);
60 h->data = pa_xnew0(struct hashmap_entry*, h->size = BUCKETS);
61 h->first_entry = NULL;
63 h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func;
64 h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func;
69 static void remove(pa_hashmap *h, struct hashmap_entry *e) {
74 e->next->previous = e->previous;
76 e->previous->next = e->next;
78 h->first_entry = e->next;
81 e->bucket_next->bucket_previous = e->bucket_previous;
82 if (e->bucket_previous)
83 e->bucket_previous->bucket_next = e->bucket_next;
85 assert(e->hash < h->size);
86 h->data[e->hash] = e->bucket_next;
93 void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) {
96 while (h->first_entry) {
98 free_func(h->first_entry->value, userdata);
99 remove(h, h->first_entry);
106 static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) {
107 struct hashmap_entry *e;
109 assert(hash < h->size);
111 for (e = h->data[hash]; e; e = e->bucket_next)
112 if (h->compare_func(e->key, key) == 0)
118 int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) {
119 struct hashmap_entry *e;
123 hash = h->hash_func(key) % h->size;
125 if ((e = get(h, hash, key)))
128 e = pa_xnew(struct hashmap_entry, 1);
134 e->next = h->first_entry;
136 h->first_entry->previous = e;
139 e->bucket_previous = NULL;
140 e->bucket_next = h->data[hash];
142 h->data[hash]->bucket_previous = e;
149 void* pa_hashmap_get(pa_hashmap *h, const void *key) {
151 struct hashmap_entry *e;
155 hash = h->hash_func(key) % h->size;
157 if (!(e = get(h, hash, key)))
163 void* pa_hashmap_remove(pa_hashmap *h, const void *key) {
164 struct hashmap_entry *e;
170 hash = h->hash_func(key) % h->size;
172 if (!(e = get(h, hash, key)))
180 unsigned pa_hashmap_size(pa_hashmap *h) {
184 void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) {
189 *state = h->first_entry;
191 *state = ((struct hashmap_entry*) *state)->next;
200 *key = ((struct hashmap_entry*) *state)->key;
202 return ((struct hashmap_entry*) *state)->value;
205 void* pa_hashmap_steal_first(pa_hashmap *h) {
213 data = h->first_entry->value;
214 remove(h, h->first_entry);
218 void *pa_hashmap_get_first(pa_hashmap *h) {
224 return h->first_entry->value;