4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2014 Michal Schmidt
9 systemd is free software; you can redistribute it and/or modify it
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
12 (at your option) any later version.
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
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "siphash24.h"
30 * A hash table implementation. As a minor optimization a NULL hashmap object
31 * will be treated as empty hashmap for all read operations. That way it is not
32 * necessary to instantiate an object for each Hashmap use.
34 * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap),
35 * the implemention will:
36 * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py)
37 * - perform extra checks for invalid use of iterators
40 #define HASH_KEY_SIZE 16
42 /* The base type for all hashmap and set types. Many functions in the
43 * implementation take (HashmapBase*) parameters and are run-time polymorphic,
44 * though the API is not meant to be polymorphic (do not call functions
45 * internal_*() directly). */
46 typedef struct HashmapBase HashmapBase;
48 /* Specific hashmap/set types */
49 typedef struct Hashmap Hashmap; /* Maps keys to values */
50 typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */
51 typedef struct Set Set; /* Stores just keys */
53 /* Ideally the Iterator would be an opaque struct, but it is instantiated
54 * by hashmap users, so the definition has to be here. Do not use its fields
57 unsigned idx; /* index of an entry to be iterated next */
58 const void *next_key; /* expected value of that entry's key pointer */
59 #ifdef ENABLE_DEBUG_HASHMAP
60 unsigned put_count; /* hashmap's put_count recorded at start of iteration */
61 unsigned rem_count; /* hashmap's rem_count in previous iteration */
62 unsigned prev_idx; /* idx in previous iteration */
66 #define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
67 #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
69 typedef void (*hash_func_t)(const void *p, struct siphash *state);
70 typedef int (*compare_func_t)(const void *a, const void *b);
74 compare_func_t compare;
77 void string_hash_func(const void *p, struct siphash *state);
78 int string_compare_func(const void *a, const void *b) _pure_;
79 extern const struct hash_ops string_hash_ops;
81 /* This will compare the passed pointers directly, and will not
82 * dereference them. This is hence not useful for strings or
84 void trivial_hash_func(const void *p, struct siphash *state);
85 int trivial_compare_func(const void *a, const void *b) _const_;
86 extern const struct hash_ops trivial_hash_ops;
88 /* 32bit values we can always just embedd in the pointer itself, but
89 * in order to support 32bit archs we need store 64bit values
90 * indirectly, since they don't fit in a pointer. */
91 void uint64_hash_func(const void *p, struct siphash *state);
92 int uint64_compare_func(const void *a, const void *b) _pure_;
93 extern const struct hash_ops uint64_hash_ops;
95 /* On some archs dev_t is 32bit, and on others 64bit. And sometimes
96 * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
98 void devt_hash_func(const void *p, struct siphash *state) _pure_;
99 int devt_compare_func(const void *a, const void *b) _pure_;
100 extern const struct hash_ops devt_hash_ops = {
101 .hash = devt_hash_func,
102 .compare = devt_compare_func
105 #define devt_hash_func uint64_hash_func
106 #define devt_compare_func uint64_compare_func
107 #define devt_hash_ops uint64_hash_ops
110 /* Macros for type checking */
111 #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
112 (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \
113 __builtin_types_compatible_p(typeof(h), Hashmap*) || \
114 __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \
115 __builtin_types_compatible_p(typeof(h), Set*))
117 #define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \
118 (__builtin_types_compatible_p(typeof(h), Hashmap*) || \
119 __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \
121 #define HASHMAP_BASE(h) \
122 __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \
126 #define PLAIN_HASHMAP(h) \
127 __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \
131 #ifdef ENABLE_DEBUG_HASHMAP
132 # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
133 # define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__
134 # define HASHMAP_DEBUG_PASS_ARGS , func, file, line
136 # define HASHMAP_DEBUG_PARAMS
137 # define HASHMAP_DEBUG_SRC_ARGS
138 # define HASHMAP_DEBUG_PASS_ARGS
141 Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
142 OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
143 #define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
144 #define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
146 HashmapBase *internal_hashmap_free(HashmapBase *h);
147 static inline Hashmap *hashmap_free(Hashmap *h) {
148 return (void*)internal_hashmap_free(HASHMAP_BASE(h));
150 static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) {
151 return (void*)internal_hashmap_free(HASHMAP_BASE(h));
154 HashmapBase *internal_hashmap_free_free(HashmapBase *h);
155 static inline Hashmap *hashmap_free_free(Hashmap *h) {
156 return (void*)internal_hashmap_free_free(HASHMAP_BASE(h));
158 static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) {
159 return (void*)internal_hashmap_free_free(HASHMAP_BASE(h));
162 Hashmap *hashmap_free_free_free(Hashmap *h);
163 static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) {
164 return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h));
167 HashmapBase *internal_hashmap_copy(HashmapBase *h);
168 static inline Hashmap *hashmap_copy(Hashmap *h) {
169 return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
171 static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) {
172 return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
175 int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
176 int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
177 #define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
178 #define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
180 int hashmap_put(Hashmap *h, const void *key, void *value);
181 static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) {
182 return hashmap_put(PLAIN_HASHMAP(h), key, value);
185 int hashmap_update(Hashmap *h, const void *key, void *value);
186 static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
187 return hashmap_update(PLAIN_HASHMAP(h), key, value);
190 int hashmap_replace(Hashmap *h, const void *key, void *value);
191 static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) {
192 return hashmap_replace(PLAIN_HASHMAP(h), key, value);
195 void *internal_hashmap_get(HashmapBase *h, const void *key);
196 static inline void *hashmap_get(Hashmap *h, const void *key) {
197 return internal_hashmap_get(HASHMAP_BASE(h), key);
199 static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) {
200 return internal_hashmap_get(HASHMAP_BASE(h), key);
203 void *hashmap_get2(Hashmap *h, const void *key, void **rkey);
204 static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) {
205 return hashmap_get2(PLAIN_HASHMAP(h), key, rkey);
208 bool internal_hashmap_contains(HashmapBase *h, const void *key);
209 static inline bool hashmap_contains(Hashmap *h, const void *key) {
210 return internal_hashmap_contains(HASHMAP_BASE(h), key);
212 static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) {
213 return internal_hashmap_contains(HASHMAP_BASE(h), key);
216 void *internal_hashmap_remove(HashmapBase *h, const void *key);
217 static inline void *hashmap_remove(Hashmap *h, const void *key) {
218 return internal_hashmap_remove(HASHMAP_BASE(h), key);
220 static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) {
221 return internal_hashmap_remove(HASHMAP_BASE(h), key);
224 void *hashmap_remove2(Hashmap *h, const void *key, void **rkey);
225 static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) {
226 return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey);
229 void *hashmap_remove_value(Hashmap *h, const void *key, void *value);
230 static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) {
231 return hashmap_remove_value(PLAIN_HASHMAP(h), key, value);
234 int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value);
235 static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
236 return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value);
239 int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value);
240 static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
241 return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value);
244 /* Since merging data from a OrderedHashmap into a Hashmap or vice-versa
245 * should just work, allow this by having looser type-checking here. */
246 int internal_hashmap_merge(Hashmap *h, Hashmap *other);
247 #define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other))
248 #define ordered_hashmap_merge(h, other) hashmap_merge(h, other)
250 int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add);
251 static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) {
252 return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
254 static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) {
255 return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
258 int internal_hashmap_move(HashmapBase *h, HashmapBase *other);
259 /* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */
260 static inline int hashmap_move(Hashmap *h, Hashmap *other) {
261 return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
263 static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) {
264 return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
267 int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key);
268 static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
269 return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
271 static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) {
272 return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
275 unsigned internal_hashmap_size(HashmapBase *h) _pure_;
276 static inline unsigned hashmap_size(Hashmap *h) {
277 return internal_hashmap_size(HASHMAP_BASE(h));
279 static inline unsigned ordered_hashmap_size(OrderedHashmap *h) {
280 return internal_hashmap_size(HASHMAP_BASE(h));
283 static inline bool hashmap_isempty(Hashmap *h) {
284 return hashmap_size(h) == 0;
286 static inline bool ordered_hashmap_isempty(OrderedHashmap *h) {
287 return ordered_hashmap_size(h) == 0;
290 unsigned internal_hashmap_buckets(HashmapBase *h) _pure_;
291 static inline unsigned hashmap_buckets(Hashmap *h) {
292 return internal_hashmap_buckets(HASHMAP_BASE(h));
294 static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
295 return internal_hashmap_buckets(HASHMAP_BASE(h));
298 bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
299 static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
300 return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
302 static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
303 return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
306 void internal_hashmap_clear(HashmapBase *h);
307 static inline void hashmap_clear(Hashmap *h) {
308 internal_hashmap_clear(HASHMAP_BASE(h));
310 static inline void ordered_hashmap_clear(OrderedHashmap *h) {
311 internal_hashmap_clear(HASHMAP_BASE(h));
314 void internal_hashmap_clear_free(HashmapBase *h);
315 static inline void hashmap_clear_free(Hashmap *h) {
316 internal_hashmap_clear_free(HASHMAP_BASE(h));
318 static inline void ordered_hashmap_clear_free(OrderedHashmap *h) {
319 internal_hashmap_clear_free(HASHMAP_BASE(h));
322 void hashmap_clear_free_free(Hashmap *h);
323 static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
324 hashmap_clear_free_free(PLAIN_HASHMAP(h));
328 * Note about all *_first*() functions
330 * For plain Hashmaps and Sets the order of entries is undefined.
331 * The functions find whatever entry is first in the implementation
334 * Only for OrderedHashmaps the order is well defined and finding
335 * the first entry is O(1).
338 void *internal_hashmap_steal_first(HashmapBase *h);
339 static inline void *hashmap_steal_first(Hashmap *h) {
340 return internal_hashmap_steal_first(HASHMAP_BASE(h));
342 static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
343 return internal_hashmap_steal_first(HASHMAP_BASE(h));
346 void *internal_hashmap_steal_first_key(HashmapBase *h);
347 static inline void *hashmap_steal_first_key(Hashmap *h) {
348 return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
350 static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
351 return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
354 void *internal_hashmap_first_key(HashmapBase *h) _pure_;
355 static inline void *hashmap_first_key(Hashmap *h) {
356 return internal_hashmap_first_key(HASHMAP_BASE(h));
358 static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
359 return internal_hashmap_first_key(HASHMAP_BASE(h));
362 void *internal_hashmap_first(HashmapBase *h) _pure_;
363 static inline void *hashmap_first(Hashmap *h) {
364 return internal_hashmap_first(HASHMAP_BASE(h));
366 static inline void *ordered_hashmap_first(OrderedHashmap *h) {
367 return internal_hashmap_first(HASHMAP_BASE(h));
369 #if 0 /// UNNEEDED by elogind
370 /* no hashmap_next */
371 void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
373 char **internal_hashmap_get_strv(HashmapBase *h);
374 static inline char **hashmap_get_strv(Hashmap *h) {
375 return internal_hashmap_get_strv(HASHMAP_BASE(h));
377 static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
378 return internal_hashmap_get_strv(HASHMAP_BASE(h));
382 * Hashmaps are iterated in unpredictable order.
383 * OrderedHashmaps are an exception to this. They are iterated in the order
384 * the entries were inserted.
385 * It is safe to remove the current entry.
387 #define HASHMAP_FOREACH(e, h, i) \
388 for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); )
390 #define ORDERED_HASHMAP_FOREACH(e, h, i) \
391 for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); )
393 #define HASHMAP_FOREACH_KEY(e, k, h, i) \
394 for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
396 #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
397 for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
399 DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
400 DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);
401 DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free);
402 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free);
403 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free);
404 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free);
406 #define _cleanup_hashmap_free_ _cleanup_(hashmap_freep)
407 #define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep)
408 #define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep)
409 #define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep)
410 #define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep)
411 #define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep)