1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include "alloc-util.h"
5 #include "macro.h"
6 #include "siphash24.h"
7 
8 typedef void (*hash_func_t)(const void *p, struct siphash *state);
9 typedef int (*compare_func_t)(const void *a, const void *b);
10 
11 struct hash_ops {
12         hash_func_t hash;
13         compare_func_t compare;
14         free_func_t free_key;
15         free_func_t free_value;
16 };
17 
18 #define _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func, free_key_func, free_value_func, scope) \
19         _unused_ static void (* UNIQ_T(static_hash_wrapper, uq))(const type *, struct siphash *) = hash_func; \
20         _unused_ static int (* UNIQ_T(static_compare_wrapper, uq))(const type *, const type *) = compare_func; \
21         scope const struct hash_ops name = {                            \
22                 .hash = (hash_func_t) hash_func,                        \
23                 .compare = (compare_func_t) compare_func,               \
24                 .free_key = free_key_func,                              \
25                 .free_value = free_value_func,                          \
26         }
27 
28 #define _DEFINE_FREE_FUNC(uq, type, wrapper_name, func)                 \
29         /* Type-safe free function */                                   \
30         static void UNIQ_T(wrapper_name, uq)(void *a) {                 \
31                 type *_a = a;                                           \
32                 func(_a);                                               \
33         }
34 
35 #define _DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(uq, name, type, hash_func, compare_func, free_func, scope) \
36         _DEFINE_FREE_FUNC(uq, type, static_free_wrapper, free_func);    \
37         _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func,       \
38                          UNIQ_T(static_free_wrapper, uq), NULL, scope)
39 
40 #define _DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(uq, name, type, hash_func, compare_func, type_value, free_func, scope) \
41         _DEFINE_FREE_FUNC(uq, type_value, static_free_wrapper, free_func); \
42         _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func,       \
43                          NULL, UNIQ_T(static_free_wrapper, uq), scope)
44 
45 #define _DEFINE_HASH_OPS_FULL(uq, name, type, hash_func, compare_func, free_key_func, type_value, free_value_func, scope) \
46         _DEFINE_FREE_FUNC(uq, type, static_free_key_wrapper, free_key_func); \
47         _DEFINE_FREE_FUNC(uq, type_value, static_free_value_wrapper, free_value_func); \
48         _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func,       \
49                          UNIQ_T(static_free_key_wrapper, uq),           \
50                          UNIQ_T(static_free_value_wrapper, uq), scope)
51 
52 #define DEFINE_HASH_OPS(name, type, hash_func, compare_func)            \
53         _DEFINE_HASH_OPS(UNIQ, name, type, hash_func, compare_func, NULL, NULL,)
54 
55 #define DEFINE_PRIVATE_HASH_OPS(name, type, hash_func, compare_func)    \
56         _DEFINE_HASH_OPS(UNIQ, name, type, hash_func, compare_func, NULL, NULL, static)
57 
58 #define DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(name, type, hash_func, compare_func, free_func) \
59         _DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, free_func,)
60 
61 #define DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(name, type, hash_func, compare_func, free_func) \
62         _DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, free_func, static)
63 
64 #define DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(name, type, hash_func, compare_func, value_type, free_func) \
65         _DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, value_type, free_func,)
66 
67 #define DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(name, type, hash_func, compare_func, value_type, free_func) \
68         _DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, value_type, free_func, static)
69 
70 #define DEFINE_HASH_OPS_FULL(name, type, hash_func, compare_func, free_key_func, value_type, free_value_func) \
71         _DEFINE_HASH_OPS_FULL(UNIQ, name, type, hash_func, compare_func, free_key_func, value_type, free_value_func,)
72 
73 #define DEFINE_PRIVATE_HASH_OPS_FULL(name, type, hash_func, compare_func, free_key_func, value_type, free_value_func) \
74         _DEFINE_HASH_OPS_FULL(UNIQ, name, type, hash_func, compare_func, free_key_func, value_type, free_value_func, static)
75 
76 void string_hash_func(const char *p, struct siphash *state);
77 #define string_compare_func strcmp
78 extern const struct hash_ops string_hash_ops;
79 extern const struct hash_ops string_hash_ops_free;
80 extern const struct hash_ops string_hash_ops_free_free;
81 
82 void path_hash_func(const char *p, struct siphash *state);
83 extern const struct hash_ops path_hash_ops;
84 extern const struct hash_ops path_hash_ops_free;
85 extern const struct hash_ops path_hash_ops_free_free;
86 
87 /* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings
88  * or suchlike. */
89 void trivial_hash_func(const void *p, struct siphash *state);
90 int trivial_compare_func(const void *a, const void *b) _const_;
91 extern const struct hash_ops trivial_hash_ops;
92 extern const struct hash_ops trivial_hash_ops_free;
93 extern const struct hash_ops trivial_hash_ops_free_free;
94 
95 /* 32bit values we can always just embed in the pointer itself, but in order to support 32bit archs we need store 64bit
96  * values indirectly, since they don't fit in a pointer. */
97 void uint64_hash_func(const uint64_t *p, struct siphash *state);
98 int uint64_compare_func(const uint64_t *a, const uint64_t *b) _pure_;
99 extern const struct hash_ops uint64_hash_ops;
100 
101 /* On some archs dev_t is 32bit, and on others 64bit. And sometimes it's 64bit on 32bit archs, and sometimes 32bit on
102  * 64bit archs. Yuck! */
103 #if SIZEOF_DEV_T != 8
104 void devt_hash_func(const dev_t *p, struct siphash *state) _pure_;
105 #else
106 #define devt_hash_func uint64_hash_func
107 #endif
108 
109 int devt_compare_func(const dev_t *a, const dev_t *b) _pure_;
110 extern const struct hash_ops devt_hash_ops;
111