• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 15057632786

15 May 2025 09:01PM UTC coverage: 72.267% (+0.02%) from 72.244%
15057632786

push

github

bluca
man: document how to hook stuff into system wakeup

Fixes: #6364

298523 of 413084 relevant lines covered (72.27%)

738132.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.31
/src/basic/hashmap.h
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
#pragma once
3

4
#include <limits.h>
5
#include <stdbool.h>
6
#include <stddef.h>
7

8
#include "hash-funcs.h"
9
#include "iterator.h"
10
#include "macro.h"
11

12
/*
13
 * A hash table implementation. As a minor optimization a NULL hashmap object
14
 * will be treated as empty hashmap for all read operations. That way it is not
15
 * necessary to instantiate an object for each Hashmap use.
16
 *
17
 * If ENABLE_DEBUG_HASHMAP is defined (by configuring with -Ddebug-extra=hashmap),
18
 * the implementation will:
19
 * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py)
20
 * - perform extra checks for invalid use of iterators
21
 */
22

23
#define HASH_KEY_SIZE 16
24

25
typedef void* (*hashmap_destroy_t)(void *p);
26

27
/* The base type for all hashmap and set types. Many functions in the implementation take (HashmapBase*)
28
 * parameters and are run-time polymorphic, though the API is not meant to be polymorphic (do not call
29
 * underscore-prefixed functions directly). */
30
typedef struct HashmapBase HashmapBase;
31

32
/* Specific hashmap/set types */
33
typedef struct Hashmap Hashmap;               /* Maps keys to values */
34
typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */
35
typedef struct Set Set;                       /* Stores just keys */
36

37
typedef struct IteratedCache IteratedCache;   /* Caches the iterated order of one of the above */
38

39
/* Macros for type checking */
40
#define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
41
        (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \
42
         __builtin_types_compatible_p(typeof(h), Hashmap*) || \
43
         __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \
44
         __builtin_types_compatible_p(typeof(h), Set*))
45

46
#define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \
47
        (__builtin_types_compatible_p(typeof(h), Hashmap*) || \
48
         __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \
49

50
#define HASHMAP_BASE(h) \
51
        __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \
52
                (HashmapBase*)(h), \
53
                (void)0)
54

55
#define PLAIN_HASHMAP(h) \
56
        __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \
57
                (Hashmap*)(h), \
58
                (void)0)
59

60
Hashmap* hashmap_new(const struct hash_ops *hash_ops);
61
OrderedHashmap* ordered_hashmap_new(const struct hash_ops *hash_ops);
62

63
#define hashmap_free_and_replace(a, b)                          \
64
        free_and_replace_full(a, b, hashmap_free)
65
#define ordered_hashmap_free_and_replace(a, b)                  \
66
        free_and_replace_full(a, b, ordered_hashmap_free)
67

68
HashmapBase* _hashmap_free(HashmapBase *h);
69
static inline Hashmap* hashmap_free(Hashmap *h) {
4,250,381✔
70
        return (void*) _hashmap_free(HASHMAP_BASE(h));
3,621,453✔
71
}
72
static inline OrderedHashmap* ordered_hashmap_free(OrderedHashmap *h) {
4,408,758✔
73
        return (void*) _hashmap_free(HASHMAP_BASE(h));
3,176,171✔
74
}
75

76
IteratedCache* iterated_cache_free(IteratedCache *cache);
77
int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries);
78

79
HashmapBase* _hashmap_copy(HashmapBase *h);
80
static inline Hashmap* hashmap_copy(Hashmap *h) {
1✔
81
        return (Hashmap*) _hashmap_copy(HASHMAP_BASE(h));
1✔
82
}
83
static inline OrderedHashmap* ordered_hashmap_copy(OrderedHashmap *h) {
1✔
84
        return (OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h));
1✔
85
}
86

87
int hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops);
88
int hashmap_ensure_put(Hashmap **h, const struct hash_ops *hash_ops, const void *key, void *value);
89
int ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops);
90
int hashmap_ensure_replace(Hashmap **h, const struct hash_ops *hash_ops, const void *key, void *value);
91

92
int ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value);
93
int ordered_hashmap_ensure_replace(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value);
94

95
IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h);
96
static inline IteratedCache* hashmap_iterated_cache_new(Hashmap *h) {
1✔
97
        return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h));
1✔
98
}
99
static inline IteratedCache* ordered_hashmap_iterated_cache_new(OrderedHashmap *h) {
6,301✔
100
        return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h));
6,301✔
101
}
102

103
int hashmap_put(Hashmap *h, const void *key, void *value);
104
static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) {
8,043,191✔
105
        return hashmap_put(PLAIN_HASHMAP(h), key, value);
8,043,166✔
106
}
107

108
int hashmap_put_strdup_full(Hashmap **h, const struct hash_ops *hash_ops, const char *k, const char *v);
109
static inline int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) {
17✔
110
        return hashmap_put_strdup_full(h, &string_hash_ops_free_free, k, v);
17✔
111
}
112

113
int hashmap_update(Hashmap *h, const void *key, void *value);
114
static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
4✔
115
        return hashmap_update(PLAIN_HASHMAP(h), key, value);
4✔
116
}
117

118
int hashmap_replace(Hashmap *h, const void *key, void *value);
119
static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) {
12,437,904✔
120
        return hashmap_replace(PLAIN_HASHMAP(h), key, value);
12,437,904✔
121
}
122

123
void* _hashmap_get(HashmapBase *h, const void *key);
124
static inline void *hashmap_get(Hashmap *h, const void *key) {
30,212,719✔
125
        return _hashmap_get(HASHMAP_BASE(h), key);
29,631,882✔
126
}
127
static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) {
29,937,303✔
128
        return _hashmap_get(HASHMAP_BASE(h), key);
29,937,303✔
129
}
130

131
void* hashmap_get2(Hashmap *h, const void *key, void **rkey);
132
static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) {
12,429,627✔
133
        return hashmap_get2(PLAIN_HASHMAP(h), key, rkey);
12,429,627✔
134
}
135

136
bool _hashmap_contains(HashmapBase *h, const void *key);
137
static inline bool hashmap_contains(Hashmap *h, const void *key) {
1,250,021✔
138
        return _hashmap_contains(HASHMAP_BASE(h), key);
1,250,021✔
139
}
140
static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) {
18,823✔
141
        return _hashmap_contains(HASHMAP_BASE(h), key);
18,823✔
142
}
143

144
void* _hashmap_remove(HashmapBase *h, const void *key);
145
static inline void *hashmap_remove(Hashmap *h, const void *key) {
7,008,580✔
146
        return _hashmap_remove(HASHMAP_BASE(h), key);
7,004,836✔
147
}
148
static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) {
64,718✔
149
        return _hashmap_remove(HASHMAP_BASE(h), key);
64,718✔
150
}
151

152
void* hashmap_remove2(Hashmap *h, const void *key, void **rkey);
153
static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) {
587,372✔
154
        return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey);
587,372✔
155
}
156

157
void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value);
158
static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
396,460✔
159
        return _hashmap_remove_value(HASHMAP_BASE(h), key, value);
396,370✔
160
}
161

162
static inline void* ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) {
125,713✔
163
        return hashmap_remove_value(PLAIN_HASHMAP(h), key, value);
125,713✔
164
}
165

166
int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value);
167
static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
4✔
168
        return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value);
4✔
169
}
170

171
int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value);
172
static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
24✔
173
        return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value);
24✔
174
}
175

176
/* Since merging data from an OrderedHashmap into a Hashmap or vice-versa
177
 * should just work, allow this by having looser type-checking here. */
178
int _hashmap_merge(Hashmap *h, Hashmap *other);
179
#define hashmap_merge(h, other) _hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other))
180
#define ordered_hashmap_merge(h, other) hashmap_merge(h, other)
181

182
int _hashmap_reserve(HashmapBase *h, unsigned entries_add);
183
static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) {
16✔
184
        return _hashmap_reserve(HASHMAP_BASE(h), entries_add);
16✔
185
}
186
static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) {
1,509✔
187
        return _hashmap_reserve(HASHMAP_BASE(h), entries_add);
1,509✔
188
}
189

190
int _hashmap_move(HashmapBase *h, HashmapBase *other);
191
/* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */
192
static inline int hashmap_move(Hashmap *h, Hashmap *other) {
2,485✔
193
        return _hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
2,485✔
194
}
195
static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) {
2✔
196
        return _hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
2✔
197
}
198

199
int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key);
200
static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
5✔
201
        return _hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
5✔
202
}
203
static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) {
582✔
204
        return _hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
582✔
205
}
206

207
unsigned _hashmap_size(HashmapBase *h) _pure_;
208
static inline unsigned hashmap_size(Hashmap *h) {
1,513,406✔
209
        return _hashmap_size(HASHMAP_BASE(h));
1,173,523✔
210
}
211
static inline unsigned ordered_hashmap_size(OrderedHashmap *h) {
9,215,076✔
212
        return _hashmap_size(HASHMAP_BASE(h));
9,122,427✔
213
}
214

215
static inline bool hashmap_isempty(Hashmap *h) {
986,274✔
216
        return hashmap_size(h) == 0;
918,575✔
217
}
218
static inline bool ordered_hashmap_isempty(OrderedHashmap *h) {
1,304,846✔
219
        return ordered_hashmap_size(h) == 0;
1,304,794✔
220
}
221

222
unsigned _hashmap_buckets(HashmapBase *h) _pure_;
223
static inline unsigned hashmap_buckets(Hashmap *h) {
2,655✔
224
        return _hashmap_buckets(HASHMAP_BASE(h));
2,655✔
225
}
226
static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
8✔
227
        return _hashmap_buckets(HASHMAP_BASE(h));
8✔
228
}
229

230
bool _hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
231
static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
24,412,585✔
232
        return _hashmap_iterate(HASHMAP_BASE(h), i, value, key);
24,412,585✔
233
}
234
static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
9,708,082✔
235
        return _hashmap_iterate(HASHMAP_BASE(h), i, value, key);
9,708,091✔
236
}
237

238
void _hashmap_clear(HashmapBase *h);
239
static inline void hashmap_clear(Hashmap *h) {
112,167✔
240
        _hashmap_clear(HASHMAP_BASE(h));
112,167✔
241
}
92,889✔
242
static inline void ordered_hashmap_clear(OrderedHashmap *h) {
18,139✔
243
        _hashmap_clear(HASHMAP_BASE(h));
18,139✔
244
}
24✔
245

246
/*
247
 * Note about all *_first*() functions
248
 *
249
 * For plain Hashmaps and Sets the order of entries is undefined.
250
 * The functions find whatever entry is first in the implementation
251
 * internal order.
252
 *
253
 * Only for OrderedHashmaps the order is well defined and finding
254
 * the first entry is O(1).
255
 */
256

257
void *_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key);
258
static inline void *hashmap_steal_first_key_and_value(Hashmap *h, void **ret) {
43,212✔
259
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
43,212✔
260
}
261
static inline void *ordered_hashmap_steal_first_key_and_value(OrderedHashmap *h, void **ret) {
×
262
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
×
263
}
264
static inline void *hashmap_first_key_and_value(Hashmap *h, void **ret) {
265
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
266
}
267
static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void **ret) {
268
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
269
}
270

271
static inline void *hashmap_steal_first(Hashmap *h) {
395,846✔
272
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
395,846✔
273
}
274
static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
7,654,847✔
275
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
7,654,847✔
276
}
277
static inline void *hashmap_first(Hashmap *h) {
52,143✔
278
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
52,143✔
279
}
280
static inline void *ordered_hashmap_first(OrderedHashmap *h) {
311,467✔
281
        return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
311,467✔
282
}
283

284
static inline void *_hashmap_first_key(HashmapBase *h, bool remove) {
921,513✔
285
        void *key = NULL;
921,513✔
286

287
        (void) _hashmap_first_key_and_value(HASHMAP_BASE(h), remove, &key);
921,513✔
288
        return key;
921,513✔
289
}
290
static inline void *hashmap_steal_first_key(Hashmap *h) {
908,134✔
291
        return _hashmap_first_key(HASHMAP_BASE(h), true);
908,134✔
292
}
293
static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
2✔
294
        return _hashmap_first_key(HASHMAP_BASE(h), true);
2✔
295
}
296
static inline void *hashmap_first_key(Hashmap *h) {
12,993✔
297
        return _hashmap_first_key(HASHMAP_BASE(h), false);
12,993✔
298
}
299
static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
384✔
300
        return _hashmap_first_key(HASHMAP_BASE(h), false);
384✔
301
}
302

303
/* no hashmap_next */
304
void* ordered_hashmap_next(OrderedHashmap *h, const void *key);
305

306
char** _hashmap_get_strv(HashmapBase *h);
307
static inline char** hashmap_get_strv(Hashmap *h) {
1✔
308
        return _hashmap_get_strv(HASHMAP_BASE(h));
1✔
309
}
310
static inline char** ordered_hashmap_get_strv(OrderedHashmap *h) {
1✔
311
        return _hashmap_get_strv(HASHMAP_BASE(h));
1✔
312
}
313

314
int _hashmap_dump_sorted(HashmapBase *h, void ***ret, size_t *ret_n);
315
static inline int hashmap_dump_sorted(Hashmap *h, void ***ret, size_t *ret_n) {
106,971✔
316
        return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n);
106,971✔
317
}
318
static inline int ordered_hashmap_dump_sorted(OrderedHashmap *h, void ***ret, size_t *ret_n) {
4✔
319
        return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n);
4✔
320
}
321
static inline int set_dump_sorted(Set *h, void ***ret, size_t *ret_n) {
448✔
322
        return _hashmap_dump_sorted(HASHMAP_BASE(h), ret, ret_n);
448✔
323
}
324

325
int _hashmap_dump_keys_sorted(HashmapBase *h, void ***ret, size_t *ret_n);
326
static inline int hashmap_dump_keys_sorted(Hashmap *h, void ***ret, size_t *ret_n) {
87✔
327
        return _hashmap_dump_keys_sorted(HASHMAP_BASE(h), ret, ret_n);
87✔
328
}
329
static inline int ordered_hashmap_dump_keys_sorted(OrderedHashmap *h, void ***ret, size_t *ret_n) {
2✔
330
        return _hashmap_dump_keys_sorted(HASHMAP_BASE(h), ret, ret_n);
2✔
331
}
332

333
/*
334
 * Hashmaps are iterated in unpredictable order.
335
 * OrderedHashmaps are an exception to this. They are iterated in the order
336
 * the entries were inserted.
337
 * It is safe to remove the current entry.
338
 */
339
#define _HASHMAP_BASE_FOREACH(e, h, i) \
340
        for (Iterator i = ITERATOR_FIRST; _hashmap_iterate((h), &i, (void**)&(e), NULL); )
341
#define HASHMAP_BASE_FOREACH(e, h) \
342
        _HASHMAP_BASE_FOREACH(e, h, UNIQ_T(i, UNIQ))
343

344
#define _HASHMAP_FOREACH(e, h, i) \
345
        for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), NULL); )
346
#define HASHMAP_FOREACH(e, h) \
347
        _HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ))
348

349
#define _ORDERED_HASHMAP_FOREACH(e, h, i) \
350
        for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), NULL); )
351
#define ORDERED_HASHMAP_FOREACH(e, h) \
352
        _ORDERED_HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ))
353

354
#define _HASHMAP_BASE_FOREACH_KEY(e, k, h, i) \
355
        for (Iterator i = ITERATOR_FIRST; _hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); )
356
#define HASHMAP_BASE_FOREACH_KEY(e, k, h) \
357
        _HASHMAP_BASE_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ))
358

359
#define _HASHMAP_FOREACH_KEY(e, k, h, i) \
360
        for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); )
361
#define HASHMAP_FOREACH_KEY(e, k, h) \
362
        _HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ))
363

364
#define _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
365
        for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); )
366
#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) \
367
        _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ))
368

369
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
746,873✔
370
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free);
58,087✔
371

372
#define _cleanup_hashmap_free_ _cleanup_(hashmap_freep)
373
#define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep)
374

375
DEFINE_TRIVIAL_CLEANUP_FUNC(IteratedCache*, iterated_cache_free);
376

377
#define _cleanup_iterated_cache_free_ _cleanup_(iterated_cache_freep)
378

379
void hashmap_trim_pools(void);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc