]>
Commit | Line | Data |
---|---|---|
03467c88 | 1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
60918275 | 2 | |
c2f1db8f | 3 | #pragma once |
60918275 | 4 | |
a7334b09 LP |
5 | /*** |
6 | This file is part of systemd. | |
7 | ||
8 | Copyright 2010 Lennart Poettering | |
89439d4f | 9 | Copyright 2014 Michal Schmidt |
a7334b09 LP |
10 | |
11 | systemd is free software; you can redistribute it and/or modify it | |
5430f7f2 LP |
12 | under the terms of the GNU Lesser General Public License as published by |
13 | the Free Software Foundation; either version 2.1 of the License, or | |
a7334b09 LP |
14 | (at your option) any later version. |
15 | ||
16 | systemd is distributed in the hope that it will be useful, but | |
17 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
5430f7f2 | 19 | Lesser General Public License for more details. |
a7334b09 | 20 | |
5430f7f2 | 21 | You should have received a copy of the GNU Lesser General Public License |
a7334b09 LP |
22 | along with systemd; If not, see <http://www.gnu.org/licenses/>. |
23 | ***/ | |
24 | ||
60918275 LP |
25 | #include <stdbool.h> |
26 | ||
44a6b1b6 | 27 | #include "macro.h" |
b826ab58 | 28 | #include "siphash24.h" |
5e2f14e6 | 29 | #include "util.h" |
44a6b1b6 | 30 | |
89439d4f MS |
31 | /* |
32 | * A hash table implementation. As a minor optimization a NULL hashmap object | |
33 | * will be treated as empty hashmap for all read operations. That way it is not | |
34 | * necessary to instantiate an object for each Hashmap use. | |
35 | * | |
fc86aa0e | 36 | * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap), |
89439d4f MS |
37 | * the implemention will: |
38 | * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py) | |
39 | * - perform extra checks for invalid use of iterators | |
40 | */ | |
60918275 | 41 | |
9bf3b535 LP |
42 | #define HASH_KEY_SIZE 16 |
43 | ||
89439d4f MS |
44 | /* The base type for all hashmap and set types. Many functions in the |
45 | * implementation take (HashmapBase*) parameters and are run-time polymorphic, | |
46 | * though the API is not meant to be polymorphic (do not call functions | |
90df619e | 47 | * internal_*() directly). */ |
89439d4f MS |
48 | typedef struct HashmapBase HashmapBase; |
49 | ||
50 | /* Specific hashmap/set types */ | |
51 | typedef struct Hashmap Hashmap; /* Maps keys to values */ | |
52 | typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */ | |
53 | typedef struct Set Set; /* Stores just keys */ | |
54 | ||
55 | /* Ideally the Iterator would be an opaque struct, but it is instantiated | |
56 | * by hashmap users, so the definition has to be here. Do not use its fields | |
57 | * directly. */ | |
58 | typedef struct { | |
59 | unsigned idx; /* index of an entry to be iterated next */ | |
60 | const void *next_key; /* expected value of that entry's key pointer */ | |
fc86aa0e | 61 | #ifdef ENABLE_DEBUG_HASHMAP |
89439d4f MS |
62 | unsigned put_count; /* hashmap's put_count recorded at start of iteration */ |
63 | unsigned rem_count; /* hashmap's rem_count in previous iteration */ | |
64 | unsigned prev_idx; /* idx in previous iteration */ | |
65 | #endif | |
66 | } Iterator; | |
034c6ed7 | 67 | |
89439d4f MS |
68 | #define _IDX_ITERATOR_FIRST (UINT_MAX - 1) |
69 | #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) | |
60918275 | 70 | |
b826ab58 | 71 | typedef void (*hash_func_t)(const void *p, struct siphash *state); |
60918275 LP |
72 | typedef int (*compare_func_t)(const void *a, const void *b); |
73 | ||
d5099efc MS |
74 | struct hash_ops { |
75 | hash_func_t hash; | |
76 | compare_func_t compare; | |
77 | }; | |
78 | ||
b826ab58 | 79 | void string_hash_func(const void *p, struct siphash *state); |
44a6b1b6 | 80 | int string_compare_func(const void *a, const void *b) _pure_; |
d5099efc | 81 | extern const struct hash_ops string_hash_ops; |
60918275 | 82 | |
1210bc66 LP |
83 | /* This will compare the passed pointers directly, and will not |
84 | * dereference them. This is hence not useful for strings or | |
85 | * suchlike. */ | |
b826ab58 | 86 | void trivial_hash_func(const void *p, struct siphash *state); |
44a6b1b6 | 87 | int trivial_compare_func(const void *a, const void *b) _const_; |
d5099efc | 88 | extern const struct hash_ops trivial_hash_ops; |
60918275 | 89 | |
de99c9dc LP |
90 | /* 32bit values we can always just embedd in the pointer itself, but |
91 | * in order to support 32bit archs we need store 64bit values | |
92 | * indirectly, since they don't fit in a pointer. */ | |
b826ab58 | 93 | void uint64_hash_func(const void *p, struct siphash *state); |
44a6b1b6 | 94 | int uint64_compare_func(const void *a, const void *b) _pure_; |
d5099efc | 95 | extern const struct hash_ops uint64_hash_ops; |
a4bcff5b | 96 | |
de99c9dc LP |
97 | /* On some archs dev_t is 32bit, and on others 64bit. And sometimes |
98 | * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */ | |
99 | #if SIZEOF_DEV_T != 8 | |
b826ab58 | 100 | void devt_hash_func(const void *p, struct siphash *state) _pure_; |
de99c9dc | 101 | int devt_compare_func(const void *a, const void *b) _pure_; |
d5099efc MS |
102 | extern const struct hash_ops devt_hash_ops = { |
103 | .hash = devt_hash_func, | |
104 | .compare = devt_compare_func | |
105 | }; | |
de99c9dc | 106 | #else |
de99c9dc LP |
107 | #define devt_hash_func uint64_hash_func |
108 | #define devt_compare_func uint64_compare_func | |
d5099efc | 109 | #define devt_hash_ops uint64_hash_ops |
de99c9dc LP |
110 | #endif |
111 | ||
89439d4f MS |
112 | /* Macros for type checking */ |
113 | #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \ | |
114 | (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \ | |
115 | __builtin_types_compatible_p(typeof(h), Hashmap*) || \ | |
116 | __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \ | |
117 | __builtin_types_compatible_p(typeof(h), Set*)) | |
118 | ||
119 | #define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \ | |
120 | (__builtin_types_compatible_p(typeof(h), Hashmap*) || \ | |
121 | __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \ | |
122 | ||
123 | #define HASHMAP_BASE(h) \ | |
124 | __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \ | |
125 | (HashmapBase*)(h), \ | |
126 | (void)0) | |
127 | ||
128 | #define PLAIN_HASHMAP(h) \ | |
129 | __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \ | |
130 | (Hashmap*)(h), \ | |
131 | (void)0) | |
132 | ||
fc86aa0e | 133 | #ifdef ENABLE_DEBUG_HASHMAP |
89439d4f MS |
134 | # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line |
135 | # define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__ | |
136 | # define HASHMAP_DEBUG_PASS_ARGS , func, file, line | |
137 | #else | |
138 | # define HASHMAP_DEBUG_PARAMS | |
139 | # define HASHMAP_DEBUG_SRC_ARGS | |
140 | # define HASHMAP_DEBUG_PASS_ARGS | |
141 | #endif | |
142 | ||
143 | Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
144 | OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
145 | #define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) | |
146 | #define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) | |
147 | ||
cfe561a4 DH |
148 | HashmapBase *internal_hashmap_free(HashmapBase *h); |
149 | static inline Hashmap *hashmap_free(Hashmap *h) { | |
150 | return (void*)internal_hashmap_free(HASHMAP_BASE(h)); | |
5ba43716 | 151 | } |
cfe561a4 DH |
152 | static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { |
153 | return (void*)internal_hashmap_free(HASHMAP_BASE(h)); | |
89439d4f MS |
154 | } |
155 | ||
cfe561a4 DH |
156 | HashmapBase *internal_hashmap_free_free(HashmapBase *h); |
157 | static inline Hashmap *hashmap_free_free(Hashmap *h) { | |
158 | return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); | |
5ba43716 | 159 | } |
cfe561a4 DH |
160 | static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { |
161 | return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); | |
5ba43716 | 162 | } |
89439d4f | 163 | |
cfe561a4 DH |
164 | Hashmap *hashmap_free_free_free(Hashmap *h); |
165 | static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { | |
166 | return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h)); | |
5ba43716 | 167 | } |
89439d4f MS |
168 | |
169 | HashmapBase *internal_hashmap_copy(HashmapBase *h); | |
170 | static inline Hashmap *hashmap_copy(Hashmap *h) { | |
171 | return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); | |
5ba43716 | 172 | } |
89439d4f MS |
173 | static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) { |
174 | return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); | |
5ba43716 | 175 | } |
60918275 | 176 | |
89439d4f MS |
177 | int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); |
178 | int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
179 | #define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) | |
180 | #define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) | |
181 | ||
60918275 | 182 | int hashmap_put(Hashmap *h, const void *key, void *value); |
5ba43716 | 183 | static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 184 | return hashmap_put(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 185 | } |
89439d4f | 186 | |
d99ae53a | 187 | int hashmap_update(Hashmap *h, const void *key, void *value); |
5ba43716 | 188 | static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 189 | return hashmap_update(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 190 | } |
89439d4f | 191 | |
3158713e | 192 | int hashmap_replace(Hashmap *h, const void *key, void *value); |
5ba43716 | 193 | static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) { |
89439d4f MS |
194 | return hashmap_replace(PLAIN_HASHMAP(h), key, value); |
195 | } | |
196 | ||
197 | void *internal_hashmap_get(HashmapBase *h, const void *key); | |
198 | static inline void *hashmap_get(Hashmap *h, const void *key) { | |
199 | return internal_hashmap_get(HASHMAP_BASE(h), key); | |
5ba43716 | 200 | } |
5ba43716 | 201 | static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { |
89439d4f | 202 | return internal_hashmap_get(HASHMAP_BASE(h), key); |
5ba43716 | 203 | } |
89439d4f | 204 | |
2f79c10e | 205 | void *hashmap_get2(Hashmap *h, const void *key, void **rkey); |
5ba43716 | 206 | static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { |
89439d4f MS |
207 | return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); |
208 | } | |
209 | ||
210 | bool internal_hashmap_contains(HashmapBase *h, const void *key); | |
211 | static inline bool hashmap_contains(Hashmap *h, const void *key) { | |
212 | return internal_hashmap_contains(HASHMAP_BASE(h), key); | |
5ba43716 | 213 | } |
5ba43716 | 214 | static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) { |
89439d4f MS |
215 | return internal_hashmap_contains(HASHMAP_BASE(h), key); |
216 | } | |
217 | ||
218 | void *internal_hashmap_remove(HashmapBase *h, const void *key); | |
219 | static inline void *hashmap_remove(Hashmap *h, const void *key) { | |
220 | return internal_hashmap_remove(HASHMAP_BASE(h), key); | |
5ba43716 | 221 | } |
5ba43716 | 222 | static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { |
89439d4f | 223 | return internal_hashmap_remove(HASHMAP_BASE(h), key); |
5ba43716 | 224 | } |
89439d4f | 225 | |
c582a3b3 | 226 | void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); |
5ba43716 | 227 | static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { |
89439d4f | 228 | return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); |
5ba43716 | 229 | } |
89439d4f | 230 | |
2f79c10e | 231 | void *hashmap_remove_value(Hashmap *h, const void *key, void *value); |
5ba43716 | 232 | static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 233 | return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 234 | } |
89439d4f | 235 | |
101d8e63 | 236 | int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value); |
5ba43716 | 237 | static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { |
89439d4f | 238 | return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value); |
5ba43716 | 239 | } |
89439d4f | 240 | |
8fe914ec | 241 | int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value); |
5ba43716 | 242 | static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { |
89439d4f | 243 | return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value); |
5ba43716 | 244 | } |
60918275 | 245 | |
89439d4f MS |
246 | /* Since merging data from a OrderedHashmap into a Hashmap or vice-versa |
247 | * should just work, allow this by having looser type-checking here. */ | |
248 | int internal_hashmap_merge(Hashmap *h, Hashmap *other); | |
249 | #define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other)) | |
250 | #define ordered_hashmap_merge(h, other) hashmap_merge(h, other) | |
251 | ||
252 | int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add); | |
253 | static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) { | |
254 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); | |
5ba43716 | 255 | } |
e4c691b5 | 256 | static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) { |
89439d4f MS |
257 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); |
258 | } | |
259 | ||
260 | int internal_hashmap_move(HashmapBase *h, HashmapBase *other); | |
261 | /* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */ | |
262 | static inline int hashmap_move(Hashmap *h, Hashmap *other) { | |
263 | return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); | |
e4c691b5 | 264 | } |
7ad63f57 | 265 | static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) { |
89439d4f MS |
266 | return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); |
267 | } | |
268 | ||
269 | int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key); | |
270 | static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { | |
271 | return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); | |
5ba43716 | 272 | } |
5ba43716 | 273 | static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) { |
89439d4f | 274 | return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); |
5ba43716 | 275 | } |
91cdde8a | 276 | |
89439d4f MS |
277 | unsigned internal_hashmap_size(HashmapBase *h) _pure_; |
278 | static inline unsigned hashmap_size(Hashmap *h) { | |
279 | return internal_hashmap_size(HASHMAP_BASE(h)); | |
280 | } | |
5ba43716 | 281 | static inline unsigned ordered_hashmap_size(OrderedHashmap *h) { |
89439d4f MS |
282 | return internal_hashmap_size(HASHMAP_BASE(h)); |
283 | } | |
284 | ||
285 | static inline bool hashmap_isempty(Hashmap *h) { | |
286 | return hashmap_size(h) == 0; | |
5ba43716 | 287 | } |
5ba43716 | 288 | static inline bool ordered_hashmap_isempty(OrderedHashmap *h) { |
89439d4f MS |
289 | return ordered_hashmap_size(h) == 0; |
290 | } | |
291 | ||
292 | unsigned internal_hashmap_buckets(HashmapBase *h) _pure_; | |
293 | static inline unsigned hashmap_buckets(Hashmap *h) { | |
294 | return internal_hashmap_buckets(HASHMAP_BASE(h)); | |
5ba43716 | 295 | } |
5ba43716 | 296 | static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) { |
89439d4f | 297 | return internal_hashmap_buckets(HASHMAP_BASE(h)); |
5ba43716 | 298 | } |
60918275 | 299 | |
8927b1da DH |
300 | bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key); |
301 | static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) { | |
302 | return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); | |
89439d4f | 303 | } |
8927b1da DH |
304 | static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) { |
305 | return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); | |
5ba43716 | 306 | } |
60918275 | 307 | |
89439d4f MS |
308 | void internal_hashmap_clear(HashmapBase *h); |
309 | static inline void hashmap_clear(Hashmap *h) { | |
310 | internal_hashmap_clear(HASHMAP_BASE(h)); | |
311 | } | |
5ba43716 | 312 | static inline void ordered_hashmap_clear(OrderedHashmap *h) { |
89439d4f MS |
313 | internal_hashmap_clear(HASHMAP_BASE(h)); |
314 | } | |
315 | ||
316 | void internal_hashmap_clear_free(HashmapBase *h); | |
317 | static inline void hashmap_clear_free(Hashmap *h) { | |
318 | internal_hashmap_clear_free(HASHMAP_BASE(h)); | |
5ba43716 | 319 | } |
5ba43716 | 320 | static inline void ordered_hashmap_clear_free(OrderedHashmap *h) { |
89439d4f | 321 | internal_hashmap_clear_free(HASHMAP_BASE(h)); |
5ba43716 | 322 | } |
89439d4f | 323 | |
fabe5c0e | 324 | void hashmap_clear_free_free(Hashmap *h); |
5ba43716 | 325 | static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) { |
89439d4f | 326 | hashmap_clear_free_free(PLAIN_HASHMAP(h)); |
5ba43716 | 327 | } |
9946996c | 328 | |
89439d4f MS |
329 | /* |
330 | * Note about all *_first*() functions | |
331 | * | |
332 | * For plain Hashmaps and Sets the order of entries is undefined. | |
333 | * The functions find whatever entry is first in the implementation | |
334 | * internal order. | |
335 | * | |
336 | * Only for OrderedHashmaps the order is well defined and finding | |
337 | * the first entry is O(1). | |
338 | */ | |
339 | ||
340 | void *internal_hashmap_steal_first(HashmapBase *h); | |
341 | static inline void *hashmap_steal_first(Hashmap *h) { | |
342 | return internal_hashmap_steal_first(HASHMAP_BASE(h)); | |
343 | } | |
5ba43716 | 344 | static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) { |
89439d4f MS |
345 | return internal_hashmap_steal_first(HASHMAP_BASE(h)); |
346 | } | |
347 | ||
348 | void *internal_hashmap_steal_first_key(HashmapBase *h); | |
349 | static inline void *hashmap_steal_first_key(Hashmap *h) { | |
350 | return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); | |
5ba43716 | 351 | } |
5ba43716 | 352 | static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) { |
89439d4f | 353 | return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); |
5ba43716 | 354 | } |
89439d4f MS |
355 | |
356 | void *internal_hashmap_first_key(HashmapBase *h) _pure_; | |
357 | static inline void *hashmap_first_key(Hashmap *h) { | |
358 | return internal_hashmap_first_key(HASHMAP_BASE(h)); | |
5ba43716 | 359 | } |
5ba43716 | 360 | static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { |
89439d4f | 361 | return internal_hashmap_first_key(HASHMAP_BASE(h)); |
5ba43716 | 362 | } |
60918275 | 363 | |
89439d4f MS |
364 | void *internal_hashmap_first(HashmapBase *h) _pure_; |
365 | static inline void *hashmap_first(Hashmap *h) { | |
366 | return internal_hashmap_first(HASHMAP_BASE(h)); | |
5ba43716 | 367 | } |
89439d4f MS |
368 | static inline void *ordered_hashmap_first(OrderedHashmap *h) { |
369 | return internal_hashmap_first(HASHMAP_BASE(h)); | |
370 | } | |
371 | ||
372 | /* no hashmap_next */ | |
373 | void *ordered_hashmap_next(OrderedHashmap *h, const void *key); | |
3c1668da | 374 | |
89439d4f MS |
375 | char **internal_hashmap_get_strv(HashmapBase *h); |
376 | static inline char **hashmap_get_strv(Hashmap *h) { | |
377 | return internal_hashmap_get_strv(HASHMAP_BASE(h)); | |
378 | } | |
5ba43716 | 379 | static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { |
89439d4f | 380 | return internal_hashmap_get_strv(HASHMAP_BASE(h)); |
5ba43716 | 381 | } |
db1413d7 | 382 | |
89439d4f MS |
383 | /* |
384 | * Hashmaps are iterated in unpredictable order. | |
385 | * OrderedHashmaps are an exception to this. They are iterated in the order | |
386 | * the entries were inserted. | |
387 | * It is safe to remove the current entry. | |
388 | */ | |
034c6ed7 | 389 | #define HASHMAP_FOREACH(e, h, i) \ |
8927b1da | 390 | for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) |
60918275 | 391 | |
5ba43716 | 392 | #define ORDERED_HASHMAP_FOREACH(e, h, i) \ |
8927b1da | 393 | for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) |
5ba43716 | 394 | |
034c6ed7 | 395 | #define HASHMAP_FOREACH_KEY(e, k, h, i) \ |
8927b1da | 396 | for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) |
11dd41ce | 397 | |
5ba43716 | 398 | #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ |
8927b1da | 399 | for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) |
5ba43716 | 400 | |
5e2f14e6 LP |
401 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); |
402 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); | |
403 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free); | |
5ba43716 MS |
404 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free); |
405 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free); | |
406 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); | |
89439d4f | 407 | |
5e2f14e6 LP |
408 | #define _cleanup_hashmap_free_ _cleanup_(hashmap_freep) |
409 | #define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep) | |
410 | #define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep) | |
5ba43716 MS |
411 | #define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep) |
412 | #define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep) | |
413 | #define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep) |