Coverage Report

Created: 2025-07-23 06:13

/src/avahi/avahi-core/hashmap.c
Line
Count
Source (jump to first uncovered line)
1
/***
2
  This file is part of avahi.
3
4
  avahi is free software; you can redistribute it and/or modify it
5
  under the terms of the GNU Lesser General Public License as
6
  published by the Free Software Foundation; either version 2.1 of the
7
  License, or (at your option) any later version.
8
9
  avahi is distributed in the hope that it will be useful, but WITHOUT
10
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11
  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12
  Public License for more details.
13
14
  You should have received a copy of the GNU Lesser General Public
15
  License along with avahi; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17
  USA.
18
***/
19
20
#ifdef HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include <avahi-common/llist.h>
28
#include <avahi-common/domain.h>
29
#include <avahi-common/malloc.h>
30
31
#include "hashmap.h"
32
#include "util.h"
33
34
0
#define HASH_MAP_SIZE 123
35
36
typedef struct Entry Entry;
37
struct Entry {
38
    AvahiHashmap *hashmap;
39
    void *key;
40
    void *value;
41
42
    AVAHI_LLIST_FIELDS(Entry, bucket);
43
    AVAHI_LLIST_FIELDS(Entry, entries);
44
};
45
46
struct AvahiHashmap {
47
    AvahiHashFunc hash_func;
48
    AvahiEqualFunc equal_func;
49
    AvahiFreeFunc key_free_func, value_free_func;
50
51
    Entry *entries[HASH_MAP_SIZE];
52
    AVAHI_LLIST_HEAD(Entry, entries_list);
53
};
54
55
0
static Entry* entry_get(AvahiHashmap *m, const void *key) {
56
0
    unsigned idx;
57
0
    Entry *e;
58
59
0
    idx = m->hash_func(key) % HASH_MAP_SIZE;
60
61
0
    for (e = m->entries[idx]; e; e = e->bucket_next)
62
0
        if (m->equal_func(key, e->key))
63
0
            return e;
64
65
0
    return NULL;
66
0
}
67
68
0
static void entry_free(AvahiHashmap *m, Entry *e, int stolen) {
69
0
    unsigned idx;
70
0
    assert(m);
71
0
    assert(e);
72
73
0
    idx = m->hash_func(e->key) % HASH_MAP_SIZE;
74
75
0
    AVAHI_LLIST_REMOVE(Entry, bucket, m->entries[idx], e);
76
0
    AVAHI_LLIST_REMOVE(Entry, entries, m->entries_list, e);
77
78
0
    if (m->key_free_func)
79
0
        m->key_free_func(e->key);
80
0
    if (m->value_free_func && !stolen)
81
0
        m->value_free_func(e->value);
82
83
0
    avahi_free(e);
84
0
}
85
86
0
AvahiHashmap* avahi_hashmap_new(AvahiHashFunc hash_func, AvahiEqualFunc equal_func, AvahiFreeFunc key_free_func, AvahiFreeFunc value_free_func) {
87
0
    AvahiHashmap *m;
88
89
0
    assert(hash_func);
90
0
    assert(equal_func);
91
92
0
    if (!(m = avahi_new0(AvahiHashmap, 1)))
93
0
        return NULL;
94
95
0
    m->hash_func = hash_func;
96
0
    m->equal_func = equal_func;
97
0
    m->key_free_func = key_free_func;
98
0
    m->value_free_func = value_free_func;
99
100
0
    AVAHI_LLIST_HEAD_INIT(Entry, m->entries_list);
101
102
0
    return m;
103
0
}
104
105
0
void avahi_hashmap_free(AvahiHashmap *m) {
106
0
    assert(m);
107
108
0
    while (m->entries_list)
109
0
        entry_free(m, m->entries_list, 0);
110
111
0
    avahi_free(m);
112
0
}
113
114
0
void* avahi_hashmap_lookup(AvahiHashmap *m, const void *key) {
115
0
    Entry *e;
116
117
0
    assert(m);
118
119
0
    if (!(e = entry_get(m, key)))
120
0
        return NULL;
121
122
0
    return e->value;
123
0
}
124
125
0
int avahi_hashmap_insert(AvahiHashmap *m, void *key, void *value) {
126
0
    unsigned idx;
127
0
    Entry *e;
128
129
0
    assert(m);
130
131
0
    if ((e = entry_get(m, key))) {
132
0
        if (m->key_free_func)
133
0
            m->key_free_func(key);
134
0
        if (m->value_free_func)
135
0
            m->value_free_func(value);
136
137
0
        return 1;
138
0
    }
139
140
0
    if (!(e = avahi_new(Entry, 1)))
141
0
        return -1;
142
143
0
    e->hashmap = m;
144
0
    e->key = key;
145
0
    e->value = value;
146
147
0
    AVAHI_LLIST_PREPEND(Entry, entries, m->entries_list, e);
148
149
0
    idx = m->hash_func(key) % HASH_MAP_SIZE;
150
0
    AVAHI_LLIST_PREPEND(Entry, bucket, m->entries[idx], e);
151
152
0
    return 0;
153
0
}
154
155
156
0
int avahi_hashmap_replace(AvahiHashmap *m, void *key, void *value) {
157
0
    unsigned idx;
158
0
    Entry *e;
159
160
0
    assert(m);
161
162
0
    if ((e = entry_get(m, key))) {
163
0
        if (m->key_free_func)
164
0
            m->key_free_func(e->key);
165
0
        if (m->value_free_func)
166
0
            m->value_free_func(e->value);
167
168
0
        e->key = key;
169
0
        e->value = value;
170
171
0
        return 1;
172
0
    }
173
174
0
    if (!(e = avahi_new(Entry, 1)))
175
0
        return -1;
176
177
0
    e->hashmap = m;
178
0
    e->key = key;
179
0
    e->value = value;
180
181
0
    AVAHI_LLIST_PREPEND(Entry, entries, m->entries_list, e);
182
183
0
    idx = m->hash_func(key) % HASH_MAP_SIZE;
184
0
    AVAHI_LLIST_PREPEND(Entry, bucket, m->entries[idx], e);
185
186
0
    return 0;
187
0
}
188
189
0
void avahi_hashmap_remove(AvahiHashmap *m, const void *key) {
190
0
    Entry *e;
191
192
0
    assert(m);
193
194
0
    if (!(e = entry_get(m, key)))
195
0
        return;
196
197
0
    entry_free(m, e, 0);
198
0
}
199
200
0
void avahi_hashmap_foreach(AvahiHashmap *m, AvahiHashmapForeachCallback callback, void *userdata) {
201
0
    Entry *e, *next;
202
0
    assert(m);
203
0
    assert(callback);
204
205
0
    for (e = m->entries_list; e; e = next) {
206
0
        next = e->entries_next;
207
208
0
        callback(e->key, e->value, userdata);
209
0
    }
210
0
}
211
212
0
unsigned avahi_string_hash(const void *data) {
213
0
    const char *p = data;
214
0
    unsigned hash = 0;
215
216
0
    assert(p);
217
218
0
    for (; *p; p++)
219
0
        hash = 31 * hash + *p;
220
221
0
    return hash;
222
0
}
223
224
0
int avahi_string_equal(const void *a, const void *b) {
225
0
    const char *p = a, *q = b;
226
227
0
    assert(p);
228
0
    assert(q);
229
230
0
    return strcmp(p, q) == 0;
231
0
}
232
233
0
unsigned avahi_int_hash(const void *data) {
234
0
    const int *i = data;
235
236
0
    assert(i);
237
238
0
    return (unsigned) *i;
239
0
}
240
241
0
int avahi_int_equal(const void *a, const void *b) {
242
0
    const int *_a = a, *_b = b;
243
244
0
    assert(_a);
245
0
    assert(_b);
246
247
0
    return *_a == *_b;
248
0
}