hashmap: migrate documentation from Documentation/technical into header
While at it, clarify the use of `key`, `keydata`, `entry_or_key` as well as documenting the new data pointer for the compare function. Rework the example. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stefan Beller committed
Jun 30, 2017 at 12:14 UTC
1ecbf31d0298a1ed952623108e23234d5cf37086
2 files changed
+316
-341
Documentation/technical/api-hashmap.txt
deleted
-309
@@ -1,309 +0,0 @@
1
-hashmap API
2
-===========
3
-
4
-The hashmap API is a generic implementation of hash-based key-value mappings.
5
-
6
-Data Structures
7
----------------
8
-
9
-`struct hashmap`::
10
-
11
- The hash table structure. Members can be used as follows, but should
12
- not be modified directly:
13
-+
14
-The `size` member keeps track of the total number of entries (0 means the
15
-hashmap is empty).
16
-+
17
-`tablesize` is the allocated size of the hash table. A non-0 value indicates
18
-that the hashmap is initialized. It may also be useful for statistical purposes
19
-(i.e. `size / tablesize` is the current load factor).
20
-+
21
-`cmpfn` stores the comparison function specified in `hashmap_init()`. In
22
-advanced scenarios, it may be useful to change this, e.g. to switch between
23
-case-sensitive and case-insensitive lookup.
24
-+
25
-When `disallow_rehash` is set, automatic rehashes are prevented during inserts
26
-and deletes.
27
-
28
-`struct hashmap_entry`::
29
-
30
- An opaque structure representing an entry in the hash table, which must
31
- be used as first member of user data structures. Ideally it should be
32
- followed by an int-sized member to prevent unused memory on 64-bit
33
- systems due to alignment.
34
-+
35
-The `hash` member is the entry's hash code and the `next` member points to the
36
-next entry in case of collisions (i.e. if multiple entries map to the same
37
-bucket).
38
-
39
-`struct hashmap_iter`::
40
-
41
- An iterator structure, to be used with hashmap_iter_* functions.
42
-
43
-Types
44
------
45
-
46
-`int (*hashmap_cmp_fn)(const void *entry, const void *entry_or_key, const void *keydata)`::
47
-
48
- User-supplied function to test two hashmap entries for equality. Shall
49
- return 0 if the entries are equal.
50
-+
51
-This function is always called with non-NULL `entry` / `entry_or_key`
52
-parameters that have the same hash code. When looking up an entry, the `key`
53
-and `keydata` parameters to hashmap_get and hashmap_remove are always passed
54
-as second and third argument, respectively. Otherwise, `keydata` is NULL.
55
-
56
-Functions
57
----------
58
-
59
-`unsigned int strhash(const char *buf)`::
60
-`unsigned int strihash(const char *buf)`::
61
-`unsigned int memhash(const void *buf, size_t len)`::
62
-`unsigned int memihash(const void *buf, size_t len)`::
63
-`unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len)`::
64
-
65
- Ready-to-use hash functions for strings, using the FNV-1 algorithm (see
66
- http://www.isthe.com/chongo/tech/comp/fnv).
67
-+
68
-`strhash` and `strihash` take 0-terminated strings, while `memhash` and
69
-`memihash` operate on arbitrary-length memory.
70
-+
71
-`strihash` and `memihash` are case insensitive versions.
72
-+
73
-`memihash_cont` is a variant of `memihash` that allows a computation to be
74
-continued with another chunk of data.
75
-
76
-`unsigned int sha1hash(const unsigned char *sha1)`::
77
-
78
- Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code
79
- for use in hash tables. Cryptographic hashes are supposed to have
80
- uniform distribution, so in contrast to `memhash()`, this just copies
81
- the first `sizeof(int)` bytes without shuffling any bits. Note that
82
- the results will be different on big-endian and little-endian
83
- platforms, so they should not be stored or transferred over the net.
84
-
85
-`void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, size_t initial_size)`::
86
-
87
- Initializes a hashmap structure.
88
-+
89
-`map` is the hashmap to initialize.
90
-+
91
-The `equals_function` can be specified to compare two entries for equality.
92
-If NULL, entries are considered equal if their hash codes are equal.
93
-+
94
-If the total number of entries is known in advance, the `initial_size`
95
-parameter may be used to preallocate a sufficiently large table and thus
96
-prevent expensive resizing. If 0, the table is dynamically resized.
97
-
98
-`void hashmap_free(struct hashmap *map, int free_entries)`::
99
-
100
- Frees a hashmap structure and allocated memory.
101
-+
102
-`map` is the hashmap to free.
103
-+
104
-If `free_entries` is true, each hashmap_entry in the map is freed as well
105
-(using stdlib's free()).
106
-
107
-`void hashmap_entry_init(void *entry, unsigned int hash)`::
108
-
109
- Initializes a hashmap_entry structure.
110
-+
111
-`entry` points to the entry to initialize.
112
-+
113
-`hash` is the hash code of the entry.
114
-+
115
-The hashmap_entry structure does not hold references to external resources,
116
-and it is safe to just discard it once you are done with it (i.e. if
117
-your structure was allocated with xmalloc(), you can just free(3) it,
118
-and if it is on stack, you can just let it go out of scope).
119
-
120
-`void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata)`::
121
-
122
- Returns the hashmap entry for the specified key, or NULL if not found.
123
-+
124
-`map` is the hashmap structure.
125
-+
126
-`key` is a hashmap_entry structure (or user data structure that starts with
127
-hashmap_entry) that has at least been initialized with the proper hash code
128
-(via `hashmap_entry_init`).
129
-+
130
-If an entry with matching hash code is found, `key` and `keydata` are passed
131
-to `hashmap_cmp_fn` to decide whether the entry matches the key.
132
-
133
-`void *hashmap_get_from_hash(const struct hashmap *map, unsigned int hash, const void *keydata)`::
134
-
135
- Returns the hashmap entry for the specified hash code and key data,
136
- or NULL if not found.
137
-+
138
-`map` is the hashmap structure.
139
-+
140
-`hash` is the hash code of the entry to look up.
141
-+
142
-If an entry with matching hash code is found, `keydata` is passed to
143
-`hashmap_cmp_fn` to decide whether the entry matches the key. The
144
-`entry_or_key` parameter points to a bogus hashmap_entry structure that
145
-should not be used in the comparison.
146
-
147
-`void *hashmap_get_next(const struct hashmap *map, const void *entry)`::
148
-
149
- Returns the next equal hashmap entry, or NULL if not found. This can be
150
- used to iterate over duplicate entries (see `hashmap_add`).
151
-+
152
-`map` is the hashmap structure.
153
-+
154
-`entry` is the hashmap_entry to start the search from, obtained via a previous
155
-call to `hashmap_get` or `hashmap_get_next`.
156
-
157
-`void hashmap_add(struct hashmap *map, void *entry)`::
158
-
159
- Adds a hashmap entry. This allows to add duplicate entries (i.e.
160
- separate values with the same key according to hashmap_cmp_fn).
161
-+
162
-`map` is the hashmap structure.
163
-+
164
-`entry` is the entry to add.
165
-
166
-`void *hashmap_put(struct hashmap *map, void *entry)`::
167
-
168
- Adds or replaces a hashmap entry. If the hashmap contains duplicate
169
- entries equal to the specified entry, only one of them will be replaced.
170
-+
171
-`map` is the hashmap structure.
172
-+
173
-`entry` is the entry to add or replace.
174
-+
175
-Returns the replaced entry, or NULL if not found (i.e. the entry was added).
176
-
177
-`void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata)`::
178
-
179
- Removes a hashmap entry matching the specified key. If the hashmap
180
- contains duplicate entries equal to the specified key, only one of
181
- them will be removed.
182
-+
183
-`map` is the hashmap structure.
184
-+
185
-`key` is a hashmap_entry structure (or user data structure that starts with
186
-hashmap_entry) that has at least been initialized with the proper hash code
187
-(via `hashmap_entry_init`).
188
-+
189
-If an entry with matching hash code is found, `key` and `keydata` are
190
-passed to `hashmap_cmp_fn` to decide whether the entry matches the key.
191
-+
192
-Returns the removed entry, or NULL if not found.
193
-
194
-`void hashmap_disallow_rehash(struct hashmap *map, unsigned value)`::
195
-
196
- Disallow/allow automatic rehashing of the hashmap during inserts
197
- and deletes.
198
-+
199
-This is useful if the caller knows that the hashmap will be accessed
200
-by multiple threads.
201
-+
202
-The caller is still responsible for any necessary locking; this simply
203
-prevents unexpected rehashing. The caller is also responsible for properly
204
-sizing the initial hashmap to ensure good performance.
205
-+
206
-A call to allow rehashing does not force a rehash; that might happen
207
-with the next insert or delete.
208
-
209
-`void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter)`::
210
-`void *hashmap_iter_next(struct hashmap_iter *iter)`::
211
-`void *hashmap_iter_first(struct hashmap *map, struct hashmap_iter *iter)`::
212
-
213
- Used to iterate over all entries of a hashmap. Note that it is
214
- not safe to add or remove entries to the hashmap while
215
- iterating.
216
-+
217
-`hashmap_iter_init` initializes a `hashmap_iter` structure.
218
-+
219
-`hashmap_iter_next` returns the next hashmap_entry, or NULL if there are no
220
-more entries.
221
-+
222
-`hashmap_iter_first` is a combination of both (i.e. initializes the iterator
223
-and returns the first entry, if any).
224
-
225
-`const char *strintern(const char *string)`::
226
-`const void *memintern(const void *data, size_t len)`::
227
-
228
- Returns the unique, interned version of the specified string or data,
229
- similar to the `String.intern` API in Java and .NET, respectively.
230
- Interned strings remain valid for the entire lifetime of the process.
231
-+
232
-Can be used as `[x]strdup()` or `xmemdupz` replacement, except that interned
233
-strings / data must not be modified or freed.
234
-+
235
-Interned strings are best used for short strings with high probability of
236
-duplicates.
237
-+
238
-Uses a hashmap to store the pool of interned strings.
239
-
240
-Usage example
241
--------------
242
-
243
-Here's a simple usage example that maps long keys to double values.
244
-------------
245
-struct hashmap map;
246
-
247
-struct long2double {
248
- struct hashmap_entry ent; /* must be the first member! */
249
- long key;
250
- double value;
251
-};
252
-
253
-static int long2double_cmp(const struct long2double *e1, const struct long2double *e2, const void *unused)
254
-{
255
- return !(e1->key == e2->key);
256
-}
257
-
258
-void long2double_init(void)
259
-{
260
- hashmap_init(&map, (hashmap_cmp_fn) long2double_cmp, 0);
261
-}
262
-
263
-void long2double_free(void)
264
-{
265
- hashmap_free(&map, 1);
266
-}
267
-
268
-static struct long2double *find_entry(long key)
269
-{
270
- struct long2double k;
271
- hashmap_entry_init(&k, memhash(&key, sizeof(long)));
272
- k.key = key;
273
- return hashmap_get(&map, &k, NULL);
274
-}
275
-
276
-double get_value(long key)
277
-{
278
- struct long2double *e = find_entry(key);
279
- return e ? e->value : 0;
280
-}
281
-
282
-void set_value(long key, double value)
283
-{
284
- struct long2double *e = find_entry(key);
285
- if (!e) {
286
- e = malloc(sizeof(struct long2double));
287
- hashmap_entry_init(e, memhash(&key, sizeof(long)));
288
- e->key = key;
289
- hashmap_add(&map, e);
290
- }
291
- e->value = value;
292
-}
293
-------------
294
-
295
-Using variable-sized keys
296
--------------------------
297
-
298
-The `hashmap_entry_get` and `hashmap_entry_remove` functions expect an ordinary
299
-`hashmap_entry` structure as key to find the correct entry. If the key data is
300
-variable-sized (e.g. a FLEX_ARRAY string) or quite large, it is undesirable
301
-to create a full-fledged entry structure on the heap and copy all the key data
302
-into the structure.
303
-
304
-In this case, the `keydata` parameter can be used to pass
305
-variable-sized key data directly to the comparison function, and the `key`
306
-parameter can be a stripped-down, fixed size entry structure allocated on the
307
-stack.
308
-
309
-See test-hashmap.c for an example using arbitrary-length strings as keys.
hashmap.h
+316
-32
@@ -3,17 +3,123 @@
3
4
/*
5
* Generic implementation of hash-based key-value mappings.
6
- * See Documentation/technical/api-hashmap.txt.
6
+ *
7
+ * An example that maps long to a string:
8
+ * For the sake of the example this allows to lookup exact values, too
9
+ * (i.e. it is operated as a set, the value is part of the key)
10
+ * -------------------------------------
11
+ *
12
+ * struct hashmap map;
13
+ * struct long2string {
14
+ * struct hashmap_entry ent; // must be the first member!
15
+ * long key;
16
+ * char value[FLEX_ARRAY]; // be careful with allocating on stack!
17
+ * };
18
+ *
19
+ * #define COMPARE_VALUE 1
20
+ *
21
+ * static int long2string_cmp(const struct long2string *e1,
22
+ * const struct long2string *e2,
23
+ * const void *keydata, const void *userdata)
24
+ * {
25
+ * char *string = keydata;
26
+ * unsigned *flags = (unsigned*)userdata;
27
+ *
28
+ * if (flags & COMPARE_VALUE)
29
+ * return !(e1->key == e2->key) || (keydata ?
30
+ * strcmp(e1->value, keydata) : strcmp(e1->value, e2->value));
31
+ * else
32
+ * return !(e1->key == e2->key);
33
+ * }
34
+ *
35
+ * int main(int argc, char **argv)
36
+ * {
37
+ * long key;
38
+ * char *value, *action;
39
+ *
40
+ * unsigned flags = ALLOW_DUPLICATE_KEYS;
41
+ *
42
+ * hashmap_init(&map, (hashmap_cmp_fn) long2string_cmp, &flags, 0);
43
+ *
44
+ * while (scanf("%s %l %s", action, key, value)) {
45
+ *
46
+ * if (!strcmp("add", action)) {
47
+ * struct long2string *e;
48
+ * e = malloc(sizeof(struct long2string) + strlen(value));
49
+ * hashmap_entry_init(e, memhash(&key, sizeof(long)));
50
+ * e->key = key;
51
+ * memcpy(e->value, value, strlen(value));
52
+ * hashmap_add(&map, e);
53
+ * }
54
+ *
55
+ * if (!strcmp("print_all_by_key", action)) {
56
+ * flags &= ~COMPARE_VALUE;
57
+ *
58
+ * struct long2string k;
59
+ * hashmap_entry_init(&k, memhash(&key, sizeof(long)));
60
+ * k.key = key;
61
+ *
62
+ * struct long2string *e = hashmap_get(&map, &k, NULL);
63
+ * if (e) {
64
+ * printf("first: %l %s\n", e->key, e->value);
65
+ * while (e = hashmap_get_next(&map, e))
66
+ * printf("found more: %l %s\n", e->key, e->value);
67
+ * }
68
+ * }
69
+ *
70
+ * if (!strcmp("has_exact_match", action)) {
71
+ * flags |= COMPARE_VALUE;
72
+ *
73
+ * struct long2string *e;
74
+ * e = malloc(sizeof(struct long2string) + strlen(value));
75
+ * hashmap_entry_init(e, memhash(&key, sizeof(long)));
76
+ * e->key = key;
77
+ * memcpy(e->value, value, strlen(value));
78
+ *
79
+ * printf("%s found\n", hashmap_get(&map, e, NULL) ? "" : "not");
80
+ * }
81
+ *
82
+ * if (!strcmp("has_exact_match_no_heap_alloc", action)) {
83
+ * flags |= COMPARE_VALUE;
84
+ *
85
+ * struct long2string e;
86
+ * hashmap_entry_init(e, memhash(&key, sizeof(long)));
87
+ * e.key = key;
88
+ *
89
+ * printf("%s found\n", hashmap_get(&map, e, value) ? "" : "not");
90
+ * }
91
+ *
92
+ * if (!strcmp("end", action)) {
93
+ * hashmap_free(&map, 1);
94
+ * break;
95
+ * }
96
+ * }
97
+ * }
98
*/
99
9
-/* FNV-1 functions */
10
-
100
+/*
101
+ * Ready-to-use hash functions for strings, using the FNV-1 algorithm (see
102
+ * http://www.isthe.com/chongo/tech/comp/fnv).
103
+ * `strhash` and `strihash` take 0-terminated strings, while `memhash` and
104
+ * `memihash` operate on arbitrary-length memory.
105
+ * `strihash` and `memihash` are case insensitive versions.
106
+ * `memihash_cont` is a variant of `memihash` that allows a computation to be
107
+ * continued with another chunk of data.
108
+ */
109
extern unsigned int strhash(const char *buf);
110
extern unsigned int strihash(const char *buf);
111
extern unsigned int memhash(const void *buf, size_t len);
112
extern unsigned int memihash(const void *buf, size_t len);
113
extern unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len);
114
115
+/*
116
+ * Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code
117
+ * for use in hash tables. Cryptographic hashes are supposed to have
118
+ * uniform distribution, so in contrast to `memhash()`, this just copies
119
+ * the first `sizeof(int)` bytes without shuffling any bits. Note that
120
+ * the results will be different on big-endian and little-endian
121
+ * platforms, so they should not be stored or transferred over the net.
122
+ */
123
static inline unsigned int sha1hash(const unsigned char *sha1)
124
{
125
/*
@@ -25,90 +131,255 @@ static inline unsigned int sha1hash(const unsigned char *sha1)
131
return hash;
132
}
133
28
-/* data structures */
29
-
134
+/*
135
+ * struct hashmap_entry is an opaque structure representing an entry in the
136
+ * hash table, which must be used as first member of user data structures.
137
+ * Ideally it should be followed by an int-sized member to prevent unused
138
+ * memory on 64-bit systems due to alignment.
139
+ */
140
struct hashmap_entry {
141
+ /*
142
+ * next points to the next entry in case of collisions (i.e. if
143
+ * multiple entries map to the same bucket)
144
+ */
145
struct hashmap_entry *next;
146
+
147
+ /* entry's hash code */
148
unsigned int hash;
149
};
150
151
+/*
152
+ * User-supplied function to test two hashmap entries for equality. Shall
153
+ * return 0 if the entries are equal.
154
+ *
155
+ * This function is always called with non-NULL `entry` and `entry_or_key`
156
+ * parameters that have the same hash code.
157
+ *
158
+ * When looking up an entry, the `key` and `keydata` parameters to hashmap_get
159
+ * and hashmap_remove are always passed as second `entry_or_key` and third
160
+ * argument `keydata`, respectively. Otherwise, `keydata` is NULL.
161
+ *
162
+ * When it is too expensive to allocate a user entry (either because it is
163
+ * large or varialbe sized, such that it is not on the stack), then the
164
+ * relevant data to check for equality should be passed via `keydata`.
165
+ * In this case `key` can be a stripped down version of the user key data
166
+ * or even just a hashmap_entry having the correct hash.
167
+ *
168
+ * The `hashmap_cmp_fn_data` entry is the pointer given in the init function.
169
+ */
170
typedef int (*hashmap_cmp_fn)(const void *hashmap_cmp_fn_data,
171
const void *entry, const void *entry_or_key,
172
const void *keydata);
173
174
+/*
175
+ * struct hashmap is the hash table structure. Members can be used as follows,
176
+ * but should not be modified directly.
177
+ */
178
struct hashmap {
179
struct hashmap_entry **table;
180
+
181
+ /* Stores the comparison function specified in `hashmap_init()`. */
182
hashmap_cmp_fn cmpfn;
183
const void *cmpfn_data;
43
- unsigned int size, tablesize, grow_at, shrink_at;
44
- unsigned disallow_rehash : 1;
45
-};
184
47
-struct hashmap_iter {
48
- struct hashmap *map;
49
- struct hashmap_entry *next;
50
- unsigned int tablepos;
185
+ /* total number of entries (0 means the hashmap is empty) */
186
+ unsigned int size;
187
+
188
+ /*
189
+ * tablesize is the allocated size of the hash table. A non-0 value
190
+ * indicates that the hashmap is initialized. It may also be useful
191
+ * for statistical purposes (i.e. `size / tablesize` is the current
192
+ * load factor).
193
+ */
194
+ unsigned int tablesize;
195
+
196
+ unsigned int grow_at;
197
+ unsigned int shrink_at;
198
+
199
+ /* See `hashmap_disallow_rehash`. */
200
+ unsigned disallow_rehash : 1;
201
};
202
203
/* hashmap functions */
204
205
+/*
206
+ * Initializes a hashmap structure.
207
+ *
208
+ * `map` is the hashmap to initialize.
209
+ *
210
+ * The `equals_function` can be specified to compare two entries for equality.
211
+ * If NULL, entries are considered equal if their hash codes are equal.
212
+ *
213
+ * The `equals_function_data` parameter can be used to provide additional data
214
+ * (a callback cookie) that will be passed to `equals_function` each time it
215
+ * is called. This allows a single `equals_function` to implement multiple
216
+ * comparison functions.
217
+ *
218
+ * If the total number of entries is known in advance, the `initial_size`
219
+ * parameter may be used to preallocate a sufficiently large table and thus
220
+ * prevent expensive resizing. If 0, the table is dynamically resized.
221
+ */
222
extern void hashmap_init(struct hashmap *map,
223
hashmap_cmp_fn equals_function,
224
const void *equals_function_data,
225
size_t initial_size);
226
+
227
+/*
228
+ * Frees a hashmap structure and allocated memory.
229
+ *
230
+ * If `free_entries` is true, each hashmap_entry in the map is freed as well
231
+ * using stdlibs free().
232
+ */
233
extern void hashmap_free(struct hashmap *map, int free_entries);
234
235
/* hashmap_entry functions */
236
237
+/*
238
+ * Initializes a hashmap_entry structure.
239
+ *
240
+ * `entry` points to the entry to initialize.
241
+ * `hash` is the hash code of the entry.
242
+ *
243
+ * The hashmap_entry structure does not hold references to external resources,
244
+ * and it is safe to just discard it once you are done with it (i.e. if
245
+ * your structure was allocated with xmalloc(), you can just free(3) it,
246
+ * and if it is on stack, you can just let it go out of scope).
247
+ */
248
static inline void hashmap_entry_init(void *entry, unsigned int hash)
249
{
250
struct hashmap_entry *e = entry;
251
e->hash = hash;
252
e->next = NULL;
253
}
254
+
255
+/*
256
+ * Returns the hashmap entry for the specified key, or NULL if not found.
257
+ *
258
+ * `map` is the hashmap structure.
259
+ *
260
+ * `key` is a user data structure that starts with hashmap_entry that has at
261
+ * least been initialized with the proper hash code (via `hashmap_entry_init`).
262
+ *
263
+ * `keydata` is a data structure that holds just enough information to check
264
+ * for equality to a given entry.
265
+ *
266
+ * If the key data is variable-sized (e.g. a FLEX_ARRAY string) or quite large,
267
+ * it is undesirable to create a full-fledged entry structure on the heap and
268
+ * copy all the key data into the structure.
269
+ *
270
+ * In this case, the `keydata` parameter can be used to pass
271
+ * variable-sized key data directly to the comparison function, and the `key`
272
+ * parameter can be a stripped-down, fixed size entry structure allocated on the
273
+ * stack.
274
+ *
275
+ * If an entry with matching hash code is found, `key` and `keydata` are passed
276
+ * to `hashmap_cmp_fn` to decide whether the entry matches the key.
277
+ */
278
extern void *hashmap_get(const struct hashmap *map, const void *key,
70
- const void *keydata);
71
-extern void *hashmap_get_next(const struct hashmap *map, const void *entry);
72
-extern void hashmap_add(struct hashmap *map, void *entry);
73
-extern void *hashmap_put(struct hashmap *map, void *entry);
74
-extern void *hashmap_remove(struct hashmap *map, const void *key,
75
- const void *keydata);
279
+ const void *keydata);
280
281
+/*
282
+ * Returns the hashmap entry for the specified hash code and key data,
283
+ * or NULL if not found.
284
+ *
285
+ * `map` is the hashmap structure.
286
+ * `hash` is the hash code of the entry to look up.
287
+ *
288
+ * If an entry with matching hash code is found, `keydata` is passed to
289
+ * `hashmap_cmp_fn` to decide whether the entry matches the key. The
290
+ * `entry_or_key` parameter of `hashmap_cmp_fn` points to a hashmap_entry
291
+ * structure that should not be used in the comparison.
292
+ */
293
static inline void *hashmap_get_from_hash(const struct hashmap *map,
78
- unsigned int hash, const void *keydata)
294
+ unsigned int hash,
295
+ const void *keydata)
296
{
297
struct hashmap_entry key;
298
hashmap_entry_init(&key, hash);
299
return hashmap_get(map, &key, keydata);
300
}
301
302
+/*
303
+ * Returns the next equal hashmap entry, or NULL if not found. This can be
304
+ * used to iterate over duplicate entries (see `hashmap_add`).
305
+ *
306
+ * `map` is the hashmap structure.
307
+ * `entry` is the hashmap_entry to start the search from, obtained via a previous
308
+ * call to `hashmap_get` or `hashmap_get_next`.
309
+ */
310
+extern void *hashmap_get_next(const struct hashmap *map, const void *entry);
311
+
312
+/*
313
+ * Adds a hashmap entry. This allows to add duplicate entries (i.e.
314
+ * separate values with the same key according to hashmap_cmp_fn).
315
+ *
316
+ * `map` is the hashmap structure.
317
+ * `entry` is the entry to add.
318
+ */
319
+extern void hashmap_add(struct hashmap *map, void *entry);
320
+
321
+/*
322
+ * Adds or replaces a hashmap entry. If the hashmap contains duplicate
323
+ * entries equal to the specified entry, only one of them will be replaced.
324
+ *
325
+ * `map` is the hashmap structure.
326
+ * `entry` is the entry to add or replace.
327
+ * Returns the replaced entry, or NULL if not found (i.e. the entry was added).
328
+ */
329
+extern void *hashmap_put(struct hashmap *map, void *entry);
330
+
331
+/*
332
+ * Removes a hashmap entry matching the specified key. If the hashmap contains
333
+ * duplicate entries equal to the specified key, only one of them will be
334
+ * removed. Returns the removed entry, or NULL if not found.
335
+ *
336
+ * Argument explanation is the same as in `hashmap_get`.
337
+ */
338
+extern void *hashmap_remove(struct hashmap *map, const void *key,
339
+ const void *keydata);
340
+
341
+/*
342
+ * Returns the `bucket` an entry is stored in.
343
+ * Useful for multithreaded read access.
344
+ */
345
int hashmap_bucket(const struct hashmap *map, unsigned int hash);
346
347
/*
348
* Disallow/allow rehashing of the hashmap.
89
- * This is useful if the caller knows that the hashmap
90
- * needs multi-threaded access. The caller is still
91
- * required to guard/lock searches and inserts in a
92
- * manner appropriate to their usage. This simply
93
- * prevents the table from being unexpectedly re-mapped.
349
+ * This is useful if the caller knows that the hashmap needs multi-threaded
350
+ * access. The caller is still required to guard/lock searches and inserts
351
+ * in a manner appropriate to their usage. This simply prevents the table
352
+ * from being unexpectedly re-mapped.
353
*
95
- * If is up to the caller to ensure that the hashmap is
96
- * initialized to a reasonable size to prevent poor
97
- * performance.
354
+ * It is up to the caller to ensure that the hashmap is initialized to a
355
+ * reasonable size to prevent poor performance.
356
*
99
- * When value=1, prevent future rehashes on adds and deleted.
100
- * When value=0, allow future rehahses. This DOES NOT force
101
- * a rehash now.
357
+ * A call to allow rehashing does not force a rehash; that might happen
358
+ * with the next insert or delete.
359
*/
360
static inline void hashmap_disallow_rehash(struct hashmap *map, unsigned value)
361
{
362
map->disallow_rehash = value;
363
}
364
108
-/* hashmap_iter functions */
365
+/*
366
+ * Used to iterate over all entries of a hashmap. Note that it is
367
+ * not safe to add or remove entries to the hashmap while
368
+ * iterating.
369
+ */
370
+struct hashmap_iter {
371
+ struct hashmap *map;
372
+ struct hashmap_entry *next;
373
+ unsigned int tablepos;
374
+};
375
376
+/* Initializes a `hashmap_iter` structure. */
377
extern void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);
378
+
379
+/* Returns the next hashmap_entry, or NULL if there are no more entries. */
380
extern void *hashmap_iter_next(struct hashmap_iter *iter);
381
+
382
+/* Initializes the iterator and returns the first entry, if any. */
383
static inline void *hashmap_iter_first(struct hashmap *map,
384
struct hashmap_iter *iter)
385
{
@@ -116,8 +387,21 @@ static inline void *hashmap_iter_first(struct hashmap *map,
387
return hashmap_iter_next(iter);
388
}
389
119
-/* string interning */
390
+/* String interning */
391
392
+/*
393
+ * Returns the unique, interned version of the specified string or data,
394
+ * similar to the `String.intern` API in Java and .NET, respectively.
395
+ * Interned strings remain valid for the entire lifetime of the process.
396
+ *
397
+ * Can be used as `[x]strdup()` or `xmemdupz` replacement, except that interned
398
+ * strings / data must not be modified or freed.
399
+ *
400
+ * Interned strings are best used for short strings with high probability of
401
+ * duplicates.
402
+ *
403
+ * Uses a hashmap to store the pool of interned strings.
404
+ */
405
extern const void *memintern(const void *data, size_t len);
406
static inline const char *strintern(const char *string)
407
{