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