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 {