]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
c2f1db8f | 2 | #pragma once |
60918275 | 3 | |
11c3a366 | 4 | #include <limits.h> |
60918275 | 5 | #include <stdbool.h> |
11c3a366 | 6 | #include <stddef.h> |
60918275 | 7 | |
758dd67e | 8 | #include "hash-funcs.h" |
44a6b1b6 | 9 | #include "macro.h" |
5e2f14e6 | 10 | #include "util.h" |
44a6b1b6 | 11 | |
89439d4f MS |
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 | * | |
fc86aa0e | 17 | * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap), |
89439d4f MS |
18 | * the implemention 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 | */ | |
60918275 | 22 | |
9bf3b535 LP |
23 | #define HASH_KEY_SIZE 16 |
24 | ||
89439d4f MS |
25 | /* The base type for all hashmap and set types. Many functions in the |
26 | * implementation take (HashmapBase*) parameters and are run-time polymorphic, | |
27 | * though the API is not meant to be polymorphic (do not call functions | |
90df619e | 28 | * internal_*() directly). */ |
89439d4f MS |
29 | typedef struct HashmapBase HashmapBase; |
30 | ||
31 | /* Specific hashmap/set types */ | |
32 | typedef struct Hashmap Hashmap; /* Maps keys to values */ | |
33 | typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */ | |
34 | typedef struct Set Set; /* Stores just keys */ | |
35 | ||
45ea84d8 VC |
36 | typedef struct IteratedCache IteratedCache; /* Caches the iterated order of one of the above */ |
37 | ||
89439d4f MS |
38 | /* Ideally the Iterator would be an opaque struct, but it is instantiated |
39 | * by hashmap users, so the definition has to be here. Do not use its fields | |
40 | * directly. */ | |
41 | typedef struct { | |
42 | unsigned idx; /* index of an entry to be iterated next */ | |
43 | const void *next_key; /* expected value of that entry's key pointer */ | |
349cc4a5 | 44 | #if ENABLE_DEBUG_HASHMAP |
89439d4f MS |
45 | unsigned put_count; /* hashmap's put_count recorded at start of iteration */ |
46 | unsigned rem_count; /* hashmap's rem_count in previous iteration */ | |
47 | unsigned prev_idx; /* idx in previous iteration */ | |
48 | #endif | |
49 | } Iterator; | |
034c6ed7 | 50 | |
89439d4f MS |
51 | #define _IDX_ITERATOR_FIRST (UINT_MAX - 1) |
52 | #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) | |
60918275 | 53 | |
89439d4f MS |
54 | /* Macros for type checking */ |
55 | #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \ | |
56 | (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \ | |
57 | __builtin_types_compatible_p(typeof(h), Hashmap*) || \ | |
58 | __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \ | |
59 | __builtin_types_compatible_p(typeof(h), Set*)) | |
60 | ||
61 | #define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \ | |
62 | (__builtin_types_compatible_p(typeof(h), Hashmap*) || \ | |
63 | __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \ | |
64 | ||
65 | #define HASHMAP_BASE(h) \ | |
66 | __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \ | |
67 | (HashmapBase*)(h), \ | |
68 | (void)0) | |
69 | ||
70 | #define PLAIN_HASHMAP(h) \ | |
71 | __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \ | |
72 | (Hashmap*)(h), \ | |
73 | (void)0) | |
74 | ||
349cc4a5 | 75 | #if ENABLE_DEBUG_HASHMAP |
89439d4f MS |
76 | # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line |
77 | # define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__ | |
78 | # define HASHMAP_DEBUG_PASS_ARGS , func, file, line | |
79 | #else | |
80 | # define HASHMAP_DEBUG_PARAMS | |
81 | # define HASHMAP_DEBUG_SRC_ARGS | |
82 | # define HASHMAP_DEBUG_PASS_ARGS | |
83 | #endif | |
84 | ||
85 | Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
86 | OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
87 | #define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) | |
88 | #define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) | |
89 | ||
cfe561a4 DH |
90 | HashmapBase *internal_hashmap_free(HashmapBase *h); |
91 | static inline Hashmap *hashmap_free(Hashmap *h) { | |
92 | return (void*)internal_hashmap_free(HASHMAP_BASE(h)); | |
5ba43716 | 93 | } |
cfe561a4 DH |
94 | static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { |
95 | return (void*)internal_hashmap_free(HASHMAP_BASE(h)); | |
89439d4f MS |
96 | } |
97 | ||
cfe561a4 DH |
98 | HashmapBase *internal_hashmap_free_free(HashmapBase *h); |
99 | static inline Hashmap *hashmap_free_free(Hashmap *h) { | |
100 | return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); | |
5ba43716 | 101 | } |
cfe561a4 DH |
102 | static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { |
103 | return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); | |
5ba43716 | 104 | } |
89439d4f | 105 | |
cfe561a4 DH |
106 | Hashmap *hashmap_free_free_free(Hashmap *h); |
107 | static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { | |
108 | return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h)); | |
5ba43716 | 109 | } |
89439d4f | 110 | |
45ea84d8 VC |
111 | IteratedCache *iterated_cache_free(IteratedCache *cache); |
112 | int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries); | |
113 | ||
89439d4f MS |
114 | HashmapBase *internal_hashmap_copy(HashmapBase *h); |
115 | static inline Hashmap *hashmap_copy(Hashmap *h) { | |
116 | return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); | |
5ba43716 | 117 | } |
89439d4f MS |
118 | static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) { |
119 | return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); | |
5ba43716 | 120 | } |
60918275 | 121 | |
89439d4f MS |
122 | int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); |
123 | int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
124 | #define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) | |
125 | #define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) | |
126 | ||
45ea84d8 VC |
127 | IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h); |
128 | static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) { | |
129 | return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h)); | |
130 | } | |
131 | static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { | |
132 | return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h)); | |
133 | } | |
134 | ||
60918275 | 135 | int hashmap_put(Hashmap *h, const void *key, void *value); |
5ba43716 | 136 | static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 137 | return hashmap_put(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 138 | } |
89439d4f | 139 | |
d99ae53a | 140 | int hashmap_update(Hashmap *h, const void *key, void *value); |
5ba43716 | 141 | static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 142 | return hashmap_update(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 143 | } |
89439d4f | 144 | |
3158713e | 145 | int hashmap_replace(Hashmap *h, const void *key, void *value); |
5ba43716 | 146 | static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) { |
89439d4f MS |
147 | return hashmap_replace(PLAIN_HASHMAP(h), key, value); |
148 | } | |
149 | ||
150 | void *internal_hashmap_get(HashmapBase *h, const void *key); | |
151 | static inline void *hashmap_get(Hashmap *h, const void *key) { | |
152 | return internal_hashmap_get(HASHMAP_BASE(h), key); | |
5ba43716 | 153 | } |
5ba43716 | 154 | static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { |
89439d4f | 155 | return internal_hashmap_get(HASHMAP_BASE(h), key); |
5ba43716 | 156 | } |
89439d4f | 157 | |
2f79c10e | 158 | void *hashmap_get2(Hashmap *h, const void *key, void **rkey); |
5ba43716 | 159 | static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { |
89439d4f MS |
160 | return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); |
161 | } | |
162 | ||
163 | bool internal_hashmap_contains(HashmapBase *h, const void *key); | |
164 | static inline bool hashmap_contains(Hashmap *h, const void *key) { | |
165 | return internal_hashmap_contains(HASHMAP_BASE(h), key); | |
5ba43716 | 166 | } |
5ba43716 | 167 | static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) { |
89439d4f MS |
168 | return internal_hashmap_contains(HASHMAP_BASE(h), key); |
169 | } | |
170 | ||
171 | void *internal_hashmap_remove(HashmapBase *h, const void *key); | |
172 | static inline void *hashmap_remove(Hashmap *h, const void *key) { | |
173 | return internal_hashmap_remove(HASHMAP_BASE(h), key); | |
5ba43716 | 174 | } |
5ba43716 | 175 | static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { |
89439d4f | 176 | return internal_hashmap_remove(HASHMAP_BASE(h), key); |
5ba43716 | 177 | } |
89439d4f | 178 | |
c582a3b3 | 179 | void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); |
5ba43716 | 180 | static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { |
89439d4f | 181 | return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); |
5ba43716 | 182 | } |
89439d4f | 183 | |
2f79c10e | 184 | void *hashmap_remove_value(Hashmap *h, const void *key, void *value); |
5ba43716 | 185 | static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 186 | return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 187 | } |
89439d4f | 188 | |
101d8e63 | 189 | int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value); |
5ba43716 | 190 | static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { |
89439d4f | 191 | return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value); |
5ba43716 | 192 | } |
89439d4f | 193 | |
8fe914ec | 194 | int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value); |
5ba43716 | 195 | static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { |
89439d4f | 196 | return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value); |
5ba43716 | 197 | } |
60918275 | 198 | |
89439d4f MS |
199 | /* Since merging data from a OrderedHashmap into a Hashmap or vice-versa |
200 | * should just work, allow this by having looser type-checking here. */ | |
201 | int internal_hashmap_merge(Hashmap *h, Hashmap *other); | |
202 | #define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other)) | |
203 | #define ordered_hashmap_merge(h, other) hashmap_merge(h, other) | |
204 | ||
205 | int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add); | |
206 | static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) { | |
207 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); | |
5ba43716 | 208 | } |
e4c691b5 | 209 | static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) { |
89439d4f MS |
210 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); |
211 | } | |
212 | ||
213 | int internal_hashmap_move(HashmapBase *h, HashmapBase *other); | |
214 | /* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */ | |
215 | static inline int hashmap_move(Hashmap *h, Hashmap *other) { | |
216 | return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); | |
e4c691b5 | 217 | } |
7ad63f57 | 218 | static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) { |
89439d4f MS |
219 | return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); |
220 | } | |
221 | ||
222 | int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key); | |
223 | static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { | |
224 | return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); | |
5ba43716 | 225 | } |
5ba43716 | 226 | static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) { |
89439d4f | 227 | return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); |
5ba43716 | 228 | } |
91cdde8a | 229 | |
89439d4f MS |
230 | unsigned internal_hashmap_size(HashmapBase *h) _pure_; |
231 | static inline unsigned hashmap_size(Hashmap *h) { | |
232 | return internal_hashmap_size(HASHMAP_BASE(h)); | |
233 | } | |
5ba43716 | 234 | static inline unsigned ordered_hashmap_size(OrderedHashmap *h) { |
89439d4f MS |
235 | return internal_hashmap_size(HASHMAP_BASE(h)); |
236 | } | |
237 | ||
238 | static inline bool hashmap_isempty(Hashmap *h) { | |
239 | return hashmap_size(h) == 0; | |
5ba43716 | 240 | } |
5ba43716 | 241 | static inline bool ordered_hashmap_isempty(OrderedHashmap *h) { |
89439d4f MS |
242 | return ordered_hashmap_size(h) == 0; |
243 | } | |
244 | ||
245 | unsigned internal_hashmap_buckets(HashmapBase *h) _pure_; | |
246 | static inline unsigned hashmap_buckets(Hashmap *h) { | |
247 | return internal_hashmap_buckets(HASHMAP_BASE(h)); | |
5ba43716 | 248 | } |
5ba43716 | 249 | static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) { |
89439d4f | 250 | return internal_hashmap_buckets(HASHMAP_BASE(h)); |
5ba43716 | 251 | } |
60918275 | 252 | |
8927b1da DH |
253 | bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key); |
254 | static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) { | |
255 | return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); | |
89439d4f | 256 | } |
8927b1da DH |
257 | static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) { |
258 | return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); | |
5ba43716 | 259 | } |
60918275 | 260 | |
89439d4f MS |
261 | void internal_hashmap_clear(HashmapBase *h); |
262 | static inline void hashmap_clear(Hashmap *h) { | |
263 | internal_hashmap_clear(HASHMAP_BASE(h)); | |
264 | } | |
5ba43716 | 265 | static inline void ordered_hashmap_clear(OrderedHashmap *h) { |
89439d4f MS |
266 | internal_hashmap_clear(HASHMAP_BASE(h)); |
267 | } | |
268 | ||
269 | void internal_hashmap_clear_free(HashmapBase *h); | |
270 | static inline void hashmap_clear_free(Hashmap *h) { | |
271 | internal_hashmap_clear_free(HASHMAP_BASE(h)); | |
5ba43716 | 272 | } |
5ba43716 | 273 | static inline void ordered_hashmap_clear_free(OrderedHashmap *h) { |
89439d4f | 274 | internal_hashmap_clear_free(HASHMAP_BASE(h)); |
5ba43716 | 275 | } |
89439d4f | 276 | |
fabe5c0e | 277 | void hashmap_clear_free_free(Hashmap *h); |
5ba43716 | 278 | static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) { |
89439d4f | 279 | hashmap_clear_free_free(PLAIN_HASHMAP(h)); |
5ba43716 | 280 | } |
9946996c | 281 | |
89439d4f MS |
282 | /* |
283 | * Note about all *_first*() functions | |
284 | * | |
285 | * For plain Hashmaps and Sets the order of entries is undefined. | |
286 | * The functions find whatever entry is first in the implementation | |
287 | * internal order. | |
288 | * | |
289 | * Only for OrderedHashmaps the order is well defined and finding | |
290 | * the first entry is O(1). | |
291 | */ | |
292 | ||
293 | void *internal_hashmap_steal_first(HashmapBase *h); | |
294 | static inline void *hashmap_steal_first(Hashmap *h) { | |
295 | return internal_hashmap_steal_first(HASHMAP_BASE(h)); | |
296 | } | |
5ba43716 | 297 | static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) { |
89439d4f MS |
298 | return internal_hashmap_steal_first(HASHMAP_BASE(h)); |
299 | } | |
300 | ||
301 | void *internal_hashmap_steal_first_key(HashmapBase *h); | |
302 | static inline void *hashmap_steal_first_key(Hashmap *h) { | |
303 | return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); | |
5ba43716 | 304 | } |
5ba43716 | 305 | static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) { |
89439d4f | 306 | return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); |
5ba43716 | 307 | } |
89439d4f MS |
308 | |
309 | void *internal_hashmap_first_key(HashmapBase *h) _pure_; | |
310 | static inline void *hashmap_first_key(Hashmap *h) { | |
311 | return internal_hashmap_first_key(HASHMAP_BASE(h)); | |
5ba43716 | 312 | } |
5ba43716 | 313 | static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { |
89439d4f | 314 | return internal_hashmap_first_key(HASHMAP_BASE(h)); |
5ba43716 | 315 | } |
60918275 | 316 | |
89439d4f MS |
317 | void *internal_hashmap_first(HashmapBase *h) _pure_; |
318 | static inline void *hashmap_first(Hashmap *h) { | |
319 | return internal_hashmap_first(HASHMAP_BASE(h)); | |
5ba43716 | 320 | } |
89439d4f MS |
321 | static inline void *ordered_hashmap_first(OrderedHashmap *h) { |
322 | return internal_hashmap_first(HASHMAP_BASE(h)); | |
323 | } | |
324 | ||
224b0e7a ZJS |
325 | #define hashmap_clear_with_destructor(_s, _f) \ |
326 | ({ \ | |
327 | void *_item; \ | |
328 | while ((_item = hashmap_steal_first(_s))) \ | |
329 | _f(_item); \ | |
330 | }) | |
331 | #define hashmap_free_with_destructor(_s, _f) \ | |
332 | ({ \ | |
333 | hashmap_clear_with_destructor(_s, _f); \ | |
334 | hashmap_free(_s); \ | |
335 | }) | |
336 | #define ordered_hashmap_clear_with_destructor(_s, _f) \ | |
337 | ({ \ | |
338 | void *_item; \ | |
339 | while ((_item = ordered_hashmap_steal_first(_s))) \ | |
340 | _f(_item); \ | |
341 | }) | |
342 | #define ordered_hashmap_free_with_destructor(_s, _f) \ | |
343 | ({ \ | |
344 | ordered_hashmap_clear_with_destructor(_s, _f); \ | |
345 | ordered_hashmap_free(_s); \ | |
346 | }) | |
347 | ||
89439d4f MS |
348 | /* no hashmap_next */ |
349 | void *ordered_hashmap_next(OrderedHashmap *h, const void *key); | |
3c1668da | 350 | |
89439d4f MS |
351 | char **internal_hashmap_get_strv(HashmapBase *h); |
352 | static inline char **hashmap_get_strv(Hashmap *h) { | |
353 | return internal_hashmap_get_strv(HASHMAP_BASE(h)); | |
354 | } | |
5ba43716 | 355 | static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { |
89439d4f | 356 | return internal_hashmap_get_strv(HASHMAP_BASE(h)); |
5ba43716 | 357 | } |
db1413d7 | 358 | |
89439d4f MS |
359 | /* |
360 | * Hashmaps are iterated in unpredictable order. | |
361 | * OrderedHashmaps are an exception to this. They are iterated in the order | |
362 | * the entries were inserted. | |
363 | * It is safe to remove the current entry. | |
364 | */ | |
034c6ed7 | 365 | #define HASHMAP_FOREACH(e, h, i) \ |
8927b1da | 366 | for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) |
60918275 | 367 | |
5ba43716 | 368 | #define ORDERED_HASHMAP_FOREACH(e, h, i) \ |
8927b1da | 369 | for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) |
5ba43716 | 370 | |
034c6ed7 | 371 | #define HASHMAP_FOREACH_KEY(e, k, h, i) \ |
8927b1da | 372 | for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) |
11dd41ce | 373 | |
5ba43716 | 374 | #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ |
8927b1da | 375 | for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) |
5ba43716 | 376 | |
5e2f14e6 LP |
377 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); |
378 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); | |
379 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free); | |
5ba43716 MS |
380 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free); |
381 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free); | |
382 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); | |
89439d4f | 383 | |
5e2f14e6 LP |
384 | #define _cleanup_hashmap_free_ _cleanup_(hashmap_freep) |
385 | #define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep) | |
386 | #define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep) | |
5ba43716 MS |
387 | #define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep) |
388 | #define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep) | |
389 | #define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep) | |
45ea84d8 VC |
390 | |
391 | DEFINE_TRIVIAL_CLEANUP_FUNC(IteratedCache*, iterated_cache_free); | |
392 | ||
393 | #define _cleanup_iterated_cache_free_ _cleanup_(iterated_cache_freep) |