Coverage Report

Created: 2025-07-12 06:54

/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
234k
#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
145k
static Entry* entry_get(AvahiHashmap *m, const void *key) {
56
145k
    unsigned idx;
57
145k
    Entry *e;
58
59
145k
    idx = m->hash_func(key) % HASH_MAP_SIZE;
60
61
213k
    for (e = m->entries[idx]; e; e = e->bucket_next)
62
126k
        if (m->equal_func(key, e->key))
63
58.8k
            return e;
64
65
86.8k
    return NULL;
66
145k
}
67
68
44.4k
static void entry_free(AvahiHashmap *m, Entry *e, int stolen) {
69
44.4k
    unsigned idx;
70
44.4k
    assert(m);
71
44.4k
    assert(e);
72
73
44.4k
    idx = m->hash_func(e->key) % HASH_MAP_SIZE;
74
75
44.4k
    AVAHI_LLIST_REMOVE(Entry, bucket, m->entries[idx], e);
76
44.4k
    AVAHI_LLIST_REMOVE(Entry, entries, m->entries_list, e);
77
78
44.4k
    if (m->key_free_func)
79
44.4k
        m->key_free_func(e->key);
80
44.4k
    if (m->value_free_func && !stolen)
81
0
        m->value_free_func(e->value);
82
83
44.4k
    avahi_free(e);
84
44.4k
}
85
86
2.33k
AvahiHashmap* avahi_hashmap_new(AvahiHashFunc hash_func, AvahiEqualFunc equal_func, AvahiFreeFunc key_free_func, AvahiFreeFunc value_free_func) {
87
2.33k
    AvahiHashmap *m;
88
89
2.33k
    assert(hash_func);
90
2.33k
    assert(equal_func);
91
92
2.33k
    if (!(m = avahi_new0(AvahiHashmap, 1)))
93
0
        return NULL;
94
95
2.33k
    m->hash_func = hash_func;
96
2.33k
    m->equal_func = equal_func;
97
2.33k
    m->key_free_func = key_free_func;
98
2.33k
    m->value_free_func = value_free_func;
99
100
2.33k
    AVAHI_LLIST_HEAD_INIT(Entry, m->entries_list);
101
102
2.33k
    return m;
103
2.33k
}
104
105
2.33k
void avahi_hashmap_free(AvahiHashmap *m) {
106
2.33k
    assert(m);
107
108
42.2k
    while (m->entries_list)
109
39.9k
        entry_free(m, m->entries_list, 0);
110
111
2.33k
    avahi_free(m);
112
2.33k
}
113
114
77.2k
void* avahi_hashmap_lookup(AvahiHashmap *m, const void *key) {
115
77.2k
    Entry *e;
116
117
77.2k
    assert(m);
118
119
77.2k
    if (!(e = entry_get(m, key)))
120
42.4k
        return NULL;
121
122
34.8k
    return e->value;
123
77.2k
}
124
125
63.9k
int avahi_hashmap_insert(AvahiHashmap *m, void *key, void *value) {
126
63.9k
    unsigned idx;
127
63.9k
    Entry *e;
128
129
63.9k
    assert(m);
130
131
63.9k
    if ((e = entry_get(m, key))) {
132
19.4k
        if (m->key_free_func)
133
19.4k
            m->key_free_func(key);
134
19.4k
        if (m->value_free_func)
135
0
            m->value_free_func(value);
136
137
19.4k
        return 1;
138
19.4k
    }
139
140
44.4k
    if (!(e = avahi_new(Entry, 1)))
141
0
        return -1;
142
143
44.4k
    e->hashmap = m;
144
44.4k
    e->key = key;
145
44.4k
    e->value = value;
146
147
44.4k
    AVAHI_LLIST_PREPEND(Entry, entries, m->entries_list, e);
148
149
44.4k
    idx = m->hash_func(key) % HASH_MAP_SIZE;
150
44.4k
    AVAHI_LLIST_PREPEND(Entry, bucket, m->entries[idx], e);
151
152
44.4k
    return 0;
153
44.4k
}
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
4.50k
void avahi_hashmap_remove(AvahiHashmap *m, const void *key) {
190
4.50k
    Entry *e;
191
192
4.50k
    assert(m);
193
194
4.50k
    if (!(e = entry_get(m, key)))
195
0
        return;
196
197
4.50k
    entry_free(m, e, 0);
198
4.50k
}
199
200
963
void avahi_hashmap_foreach(AvahiHashmap *m, AvahiHashmapForeachCallback callback, void *userdata) {
201
963
    Entry *e, *next;
202
963
    assert(m);
203
963
    assert(callback);
204
205
24.5k
    for (e = m->entries_list; e; e = next) {
206
23.5k
        next = e->entries_next;
207
208
23.5k
        callback(e->key, e->value, userdata);
209
23.5k
    }
210
963
}
211
212
234k
unsigned avahi_string_hash(const void *data) {
213
234k
    const char *p = data;
214
234k
    unsigned hash = 0;
215
216
234k
    assert(p);
217
218
53.9M
    for (; *p; p++)
219
53.7M
        hash = 31 * hash + *p;
220
221
234k
    return hash;
222
234k
}
223
224
126k
int avahi_string_equal(const void *a, const void *b) {
225
126k
    const char *p = a, *q = b;
226
227
126k
    assert(p);
228
126k
    assert(q);
229
230
126k
    return strcmp(p, q) == 0;
231
126k
}
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
}