0001
0002
0003
0004
0005
0006
0007
0008 #ifndef __LIBBPF_HASHMAP_H
0009 #define __LIBBPF_HASHMAP_H
0010
0011 #include <stdbool.h>
0012 #include <stddef.h>
0013 #include <limits.h>
0014
0015 static inline size_t hash_bits(size_t h, int bits)
0016 {
0017
0018 if (bits == 0)
0019 return 0;
0020
0021 #if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
0022
0023 return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
0024 #elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__)
0025 return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits);
0026 #else
0027 # error "Unsupported size_t size"
0028 #endif
0029 }
0030
0031
0032 static inline size_t str_hash(const char *s)
0033 {
0034 size_t h = 0;
0035
0036 while (*s) {
0037 h = h * 31 + *s;
0038 s++;
0039 }
0040 return h;
0041 }
0042
0043 typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
0044 typedef bool (*hashmap_equal_fn)(const void *key1, const void *key2, void *ctx);
0045
0046 struct hashmap_entry {
0047 const void *key;
0048 void *value;
0049 struct hashmap_entry *next;
0050 };
0051
0052 struct hashmap {
0053 hashmap_hash_fn hash_fn;
0054 hashmap_equal_fn equal_fn;
0055 void *ctx;
0056
0057 struct hashmap_entry **buckets;
0058 size_t cap;
0059 size_t cap_bits;
0060 size_t sz;
0061 };
0062
0063 #define HASHMAP_INIT(hash_fn, equal_fn, ctx) { \
0064 .hash_fn = (hash_fn), \
0065 .equal_fn = (equal_fn), \
0066 .ctx = (ctx), \
0067 .buckets = NULL, \
0068 .cap = 0, \
0069 .cap_bits = 0, \
0070 .sz = 0, \
0071 }
0072
0073 void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn,
0074 hashmap_equal_fn equal_fn, void *ctx);
0075 struct hashmap *hashmap__new(hashmap_hash_fn hash_fn,
0076 hashmap_equal_fn equal_fn,
0077 void *ctx);
0078 void hashmap__clear(struct hashmap *map);
0079 void hashmap__free(struct hashmap *map);
0080
0081 size_t hashmap__size(const struct hashmap *map);
0082 size_t hashmap__capacity(const struct hashmap *map);
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 enum hashmap_insert_strategy {
0099 HASHMAP_ADD,
0100 HASHMAP_SET,
0101 HASHMAP_UPDATE,
0102 HASHMAP_APPEND,
0103 };
0104
0105
0106
0107
0108
0109
0110
0111
0112 int hashmap__insert(struct hashmap *map, const void *key, void *value,
0113 enum hashmap_insert_strategy strategy,
0114 const void **old_key, void **old_value);
0115
0116 static inline int hashmap__add(struct hashmap *map,
0117 const void *key, void *value)
0118 {
0119 return hashmap__insert(map, key, value, HASHMAP_ADD, NULL, NULL);
0120 }
0121
0122 static inline int hashmap__set(struct hashmap *map,
0123 const void *key, void *value,
0124 const void **old_key, void **old_value)
0125 {
0126 return hashmap__insert(map, key, value, HASHMAP_SET,
0127 old_key, old_value);
0128 }
0129
0130 static inline int hashmap__update(struct hashmap *map,
0131 const void *key, void *value,
0132 const void **old_key, void **old_value)
0133 {
0134 return hashmap__insert(map, key, value, HASHMAP_UPDATE,
0135 old_key, old_value);
0136 }
0137
0138 static inline int hashmap__append(struct hashmap *map,
0139 const void *key, void *value)
0140 {
0141 return hashmap__insert(map, key, value, HASHMAP_APPEND, NULL, NULL);
0142 }
0143
0144 bool hashmap__delete(struct hashmap *map, const void *key,
0145 const void **old_key, void **old_value);
0146
0147 bool hashmap__find(const struct hashmap *map, const void *key, void **value);
0148
0149
0150
0151
0152
0153
0154
0155 #define hashmap__for_each_entry(map, cur, bkt) \
0156 for (bkt = 0; bkt < map->cap; bkt++) \
0157 for (cur = map->buckets[bkt]; cur; cur = cur->next)
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 #define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \
0168 for (bkt = 0; bkt < map->cap; bkt++) \
0169 for (cur = map->buckets[bkt]; \
0170 cur && ({tmp = cur->next; true; }); \
0171 cur = tmp)
0172
0173
0174
0175
0176
0177
0178
0179 #define hashmap__for_each_key_entry(map, cur, _key) \
0180 for (cur = map->buckets \
0181 ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
0182 : NULL; \
0183 cur; \
0184 cur = cur->next) \
0185 if (map->equal_fn(cur->key, (_key), map->ctx))
0186
0187 #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \
0188 for (cur = map->buckets \
0189 ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
0190 : NULL; \
0191 cur && ({ tmp = cur->next; true; }); \
0192 cur = tmp) \
0193 if (map->equal_fn(cur->key, (_key), map->ctx))
0194
0195 #endif