]>
Commit | Line | Data |
---|---|---|
c2f1db8f | 1 | #pragma once |
60918275 | 2 | |
a7334b09 LP |
3 | /*** |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2010 Lennart Poettering | |
89439d4f | 7 | Copyright 2014 Michal Schmidt |
a7334b09 LP |
8 | |
9 | systemd is free software; you can redistribute it and/or modify it | |
5430f7f2 LP |
10 | under the terms of the GNU Lesser General Public License as published by |
11 | the Free Software Foundation; either version 2.1 of the License, or | |
a7334b09 LP |
12 | (at your option) any later version. |
13 | ||
14 | systemd is distributed in the hope that it will be useful, but | |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
5430f7f2 | 17 | Lesser General Public License for more details. |
a7334b09 | 18 | |
5430f7f2 | 19 | You should have received a copy of the GNU Lesser General Public License |
a7334b09 LP |
20 | along with systemd; If not, see <http://www.gnu.org/licenses/>. |
21 | ***/ | |
22 | ||
11c3a366 | 23 | #include <limits.h> |
60918275 | 24 | #include <stdbool.h> |
11c3a366 | 25 | #include <stddef.h> |
60918275 | 26 | |
758dd67e | 27 | #include "hash-funcs.h" |
44a6b1b6 | 28 | #include "macro.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 */ | |
349cc4a5 | 61 | #if 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 | |
89439d4f MS |
71 | /* Macros for type checking */ |
72 | #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \ | |
73 | (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \ | |
74 | __builtin_types_compatible_p(typeof(h), Hashmap*) || \ | |
75 | __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \ | |
76 | __builtin_types_compatible_p(typeof(h), Set*)) | |
77 | ||
78 | #define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \ | |
79 | (__builtin_types_compatible_p(typeof(h), Hashmap*) || \ | |
80 | __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \ | |
81 | ||
82 | #define HASHMAP_BASE(h) \ | |
83 | __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \ | |
84 | (HashmapBase*)(h), \ | |
85 | (void)0) | |
86 | ||
87 | #define PLAIN_HASHMAP(h) \ | |
88 | __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \ | |
89 | (Hashmap*)(h), \ | |
90 | (void)0) | |
91 | ||
349cc4a5 | 92 | #if ENABLE_DEBUG_HASHMAP |
89439d4f MS |
93 | # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line |
94 | # define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__ | |
95 | # define HASHMAP_DEBUG_PASS_ARGS , func, file, line | |
96 | #else | |
97 | # define HASHMAP_DEBUG_PARAMS | |
98 | # define HASHMAP_DEBUG_SRC_ARGS | |
99 | # define HASHMAP_DEBUG_PASS_ARGS | |
100 | #endif | |
101 | ||
102 | Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
103 | OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
104 | #define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) | |
105 | #define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) | |
106 | ||
cfe561a4 DH |
107 | HashmapBase *internal_hashmap_free(HashmapBase *h); |
108 | static inline Hashmap *hashmap_free(Hashmap *h) { | |
109 | return (void*)internal_hashmap_free(HASHMAP_BASE(h)); | |
5ba43716 | 110 | } |
cfe561a4 DH |
111 | static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { |
112 | return (void*)internal_hashmap_free(HASHMAP_BASE(h)); | |
89439d4f MS |
113 | } |
114 | ||
cfe561a4 DH |
115 | HashmapBase *internal_hashmap_free_free(HashmapBase *h); |
116 | static inline Hashmap *hashmap_free_free(Hashmap *h) { | |
117 | return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); | |
5ba43716 | 118 | } |
cfe561a4 DH |
119 | static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { |
120 | return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); | |
5ba43716 | 121 | } |
89439d4f | 122 | |
cfe561a4 DH |
123 | Hashmap *hashmap_free_free_free(Hashmap *h); |
124 | static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { | |
125 | return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h)); | |
5ba43716 | 126 | } |
89439d4f MS |
127 | |
128 | HashmapBase *internal_hashmap_copy(HashmapBase *h); | |
129 | static inline Hashmap *hashmap_copy(Hashmap *h) { | |
130 | return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); | |
5ba43716 | 131 | } |
89439d4f MS |
132 | static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) { |
133 | return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); | |
5ba43716 | 134 | } |
60918275 | 135 | |
89439d4f MS |
136 | int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); |
137 | int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); | |
138 | #define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) | |
139 | #define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) | |
140 | ||
60918275 | 141 | int hashmap_put(Hashmap *h, const void *key, void *value); |
5ba43716 | 142 | static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 143 | return hashmap_put(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 144 | } |
89439d4f | 145 | |
d99ae53a | 146 | int hashmap_update(Hashmap *h, const void *key, void *value); |
5ba43716 | 147 | static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 148 | return hashmap_update(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 149 | } |
89439d4f | 150 | |
3158713e | 151 | int hashmap_replace(Hashmap *h, const void *key, void *value); |
5ba43716 | 152 | static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) { |
89439d4f MS |
153 | return hashmap_replace(PLAIN_HASHMAP(h), key, value); |
154 | } | |
155 | ||
156 | void *internal_hashmap_get(HashmapBase *h, const void *key); | |
157 | static inline void *hashmap_get(Hashmap *h, const void *key) { | |
158 | return internal_hashmap_get(HASHMAP_BASE(h), key); | |
5ba43716 | 159 | } |
5ba43716 | 160 | static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { |
89439d4f | 161 | return internal_hashmap_get(HASHMAP_BASE(h), key); |
5ba43716 | 162 | } |
89439d4f | 163 | |
2f79c10e | 164 | void *hashmap_get2(Hashmap *h, const void *key, void **rkey); |
5ba43716 | 165 | static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { |
89439d4f MS |
166 | return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); |
167 | } | |
168 | ||
169 | bool internal_hashmap_contains(HashmapBase *h, const void *key); | |
170 | static inline bool hashmap_contains(Hashmap *h, const void *key) { | |
171 | return internal_hashmap_contains(HASHMAP_BASE(h), key); | |
5ba43716 | 172 | } |
5ba43716 | 173 | static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) { |
89439d4f MS |
174 | return internal_hashmap_contains(HASHMAP_BASE(h), key); |
175 | } | |
176 | ||
177 | void *internal_hashmap_remove(HashmapBase *h, const void *key); | |
178 | static inline void *hashmap_remove(Hashmap *h, const void *key) { | |
179 | return internal_hashmap_remove(HASHMAP_BASE(h), key); | |
5ba43716 | 180 | } |
5ba43716 | 181 | static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { |
89439d4f | 182 | return internal_hashmap_remove(HASHMAP_BASE(h), key); |
5ba43716 | 183 | } |
89439d4f | 184 | |
c582a3b3 | 185 | void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); |
5ba43716 | 186 | static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { |
89439d4f | 187 | return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); |
5ba43716 | 188 | } |
89439d4f | 189 | |
2f79c10e | 190 | void *hashmap_remove_value(Hashmap *h, const void *key, void *value); |
5ba43716 | 191 | static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { |
89439d4f | 192 | return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); |
5ba43716 | 193 | } |
89439d4f | 194 | |
101d8e63 | 195 | int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value); |
5ba43716 | 196 | static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { |
89439d4f | 197 | return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value); |
5ba43716 | 198 | } |
89439d4f | 199 | |
8fe914ec | 200 | int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value); |
5ba43716 | 201 | static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { |
89439d4f | 202 | return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value); |
5ba43716 | 203 | } |
60918275 | 204 | |
89439d4f MS |
205 | /* Since merging data from a OrderedHashmap into a Hashmap or vice-versa |
206 | * should just work, allow this by having looser type-checking here. */ | |
207 | int internal_hashmap_merge(Hashmap *h, Hashmap *other); | |
208 | #define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other)) | |
209 | #define ordered_hashmap_merge(h, other) hashmap_merge(h, other) | |
210 | ||
211 | int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add); | |
212 | static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) { | |
213 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); | |
5ba43716 | 214 | } |
e4c691b5 | 215 | static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) { |
89439d4f MS |
216 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); |
217 | } | |
218 | ||
219 | int internal_hashmap_move(HashmapBase *h, HashmapBase *other); | |
220 | /* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */ | |
221 | static inline int hashmap_move(Hashmap *h, Hashmap *other) { | |
222 | return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); | |
e4c691b5 | 223 | } |
7ad63f57 | 224 | static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) { |
89439d4f MS |
225 | return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); |
226 | } | |
227 | ||
228 | int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key); | |
229 | static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { | |
230 | return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); | |
5ba43716 | 231 | } |
5ba43716 | 232 | static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) { |
89439d4f | 233 | return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); |
5ba43716 | 234 | } |
91cdde8a | 235 | |
89439d4f MS |
236 | unsigned internal_hashmap_size(HashmapBase *h) _pure_; |
237 | static inline unsigned hashmap_size(Hashmap *h) { | |
238 | return internal_hashmap_size(HASHMAP_BASE(h)); | |
239 | } | |
5ba43716 | 240 | static inline unsigned ordered_hashmap_size(OrderedHashmap *h) { |
89439d4f MS |
241 | return internal_hashmap_size(HASHMAP_BASE(h)); |
242 | } | |
243 | ||
244 | static inline bool hashmap_isempty(Hashmap *h) { | |
245 | return hashmap_size(h) == 0; | |
5ba43716 | 246 | } |
5ba43716 | 247 | static inline bool ordered_hashmap_isempty(OrderedHashmap *h) { |
89439d4f MS |
248 | return ordered_hashmap_size(h) == 0; |
249 | } | |
250 | ||
251 | unsigned internal_hashmap_buckets(HashmapBase *h) _pure_; | |
252 | static inline unsigned hashmap_buckets(Hashmap *h) { | |
253 | return internal_hashmap_buckets(HASHMAP_BASE(h)); | |
5ba43716 | 254 | } |
5ba43716 | 255 | static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) { |
89439d4f | 256 | return internal_hashmap_buckets(HASHMAP_BASE(h)); |
5ba43716 | 257 | } |
60918275 | 258 | |
8927b1da DH |
259 | bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key); |
260 | static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) { | |
261 | return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); | |
89439d4f | 262 | } |
8927b1da DH |
263 | static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) { |
264 | return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); | |
5ba43716 | 265 | } |
60918275 | 266 | |
89439d4f MS |
267 | void internal_hashmap_clear(HashmapBase *h); |
268 | static inline void hashmap_clear(Hashmap *h) { | |
269 | internal_hashmap_clear(HASHMAP_BASE(h)); | |
270 | } | |
5ba43716 | 271 | static inline void ordered_hashmap_clear(OrderedHashmap *h) { |
89439d4f MS |
272 | internal_hashmap_clear(HASHMAP_BASE(h)); |
273 | } | |
274 | ||
275 | void internal_hashmap_clear_free(HashmapBase *h); | |
276 | static inline void hashmap_clear_free(Hashmap *h) { | |
277 | internal_hashmap_clear_free(HASHMAP_BASE(h)); | |
5ba43716 | 278 | } |
5ba43716 | 279 | static inline void ordered_hashmap_clear_free(OrderedHashmap *h) { |
89439d4f | 280 | internal_hashmap_clear_free(HASHMAP_BASE(h)); |
5ba43716 | 281 | } |
89439d4f | 282 | |
fabe5c0e | 283 | void hashmap_clear_free_free(Hashmap *h); |
5ba43716 | 284 | static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) { |
89439d4f | 285 | hashmap_clear_free_free(PLAIN_HASHMAP(h)); |
5ba43716 | 286 | } |
9946996c | 287 | |
89439d4f MS |
288 | /* |
289 | * Note about all *_first*() functions | |
290 | * | |
291 | * For plain Hashmaps and Sets the order of entries is undefined. | |
292 | * The functions find whatever entry is first in the implementation | |
293 | * internal order. | |
294 | * | |
295 | * Only for OrderedHashmaps the order is well defined and finding | |
296 | * the first entry is O(1). | |
297 | */ | |
298 | ||
299 | void *internal_hashmap_steal_first(HashmapBase *h); | |
300 | static inline void *hashmap_steal_first(Hashmap *h) { | |
301 | return internal_hashmap_steal_first(HASHMAP_BASE(h)); | |
302 | } | |
5ba43716 | 303 | static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) { |
89439d4f MS |
304 | return internal_hashmap_steal_first(HASHMAP_BASE(h)); |
305 | } | |
306 | ||
307 | void *internal_hashmap_steal_first_key(HashmapBase *h); | |
308 | static inline void *hashmap_steal_first_key(Hashmap *h) { | |
309 | return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); | |
5ba43716 | 310 | } |
5ba43716 | 311 | static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) { |
89439d4f | 312 | return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); |
5ba43716 | 313 | } |
89439d4f MS |
314 | |
315 | void *internal_hashmap_first_key(HashmapBase *h) _pure_; | |
316 | static inline void *hashmap_first_key(Hashmap *h) { | |
317 | return internal_hashmap_first_key(HASHMAP_BASE(h)); | |
5ba43716 | 318 | } |
5ba43716 | 319 | static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { |
89439d4f | 320 | return internal_hashmap_first_key(HASHMAP_BASE(h)); |
5ba43716 | 321 | } |
60918275 | 322 | |
89439d4f MS |
323 | void *internal_hashmap_first(HashmapBase *h) _pure_; |
324 | static inline void *hashmap_first(Hashmap *h) { | |
325 | return internal_hashmap_first(HASHMAP_BASE(h)); | |
5ba43716 | 326 | } |
89439d4f MS |
327 | static inline void *ordered_hashmap_first(OrderedHashmap *h) { |
328 | return internal_hashmap_first(HASHMAP_BASE(h)); | |
329 | } | |
330 | ||
331 | /* no hashmap_next */ | |
332 | void *ordered_hashmap_next(OrderedHashmap *h, const void *key); | |
3c1668da | 333 | |
89439d4f MS |
334 | char **internal_hashmap_get_strv(HashmapBase *h); |
335 | static inline char **hashmap_get_strv(Hashmap *h) { | |
336 | return internal_hashmap_get_strv(HASHMAP_BASE(h)); | |
337 | } | |
5ba43716 | 338 | static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { |
89439d4f | 339 | return internal_hashmap_get_strv(HASHMAP_BASE(h)); |
5ba43716 | 340 | } |
db1413d7 | 341 | |
89439d4f MS |
342 | /* |
343 | * Hashmaps are iterated in unpredictable order. | |
344 | * OrderedHashmaps are an exception to this. They are iterated in the order | |
345 | * the entries were inserted. | |
346 | * It is safe to remove the current entry. | |
347 | */ | |
034c6ed7 | 348 | #define HASHMAP_FOREACH(e, h, i) \ |
8927b1da | 349 | for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) |
60918275 | 350 | |
5ba43716 | 351 | #define ORDERED_HASHMAP_FOREACH(e, h, i) \ |
8927b1da | 352 | for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) |
5ba43716 | 353 | |
034c6ed7 | 354 | #define HASHMAP_FOREACH_KEY(e, k, h, i) \ |
8927b1da | 355 | for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) |
11dd41ce | 356 | |
5ba43716 | 357 | #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ |
8927b1da | 358 | for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) |
5ba43716 | 359 | |
5e2f14e6 LP |
360 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); |
361 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); | |
362 | DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free); | |
5ba43716 MS |
363 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free); |
364 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free); | |
365 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); | |
89439d4f | 366 | |
5e2f14e6 LP |
367 | #define _cleanup_hashmap_free_ _cleanup_(hashmap_freep) |
368 | #define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep) | |
369 | #define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep) | |
5ba43716 MS |
370 | #define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep) |
371 | #define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep) | |
372 | #define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep) |