File: stringmap.c

package info (click to toggle)
wget2 1.99.1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 13,468 kB
  • sloc: ansic: 88,607; sh: 10,241; makefile: 501; xml: 182; sed: 16
file content (372 lines) | stat: -rw-r--r-- 10,502 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/*
 * Copyright(c) 2012 Tim Ruehsen
 * Copyright(c) 2015-2018 Free Software Foundation, Inc.
 *
 * This file is part of libwget.
 *
 * Libwget is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Libwget is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with libwget.  If not, see <https://www.gnu.org/licenses/>.
 *
 *
 * stringmap routines
 *
 * Changelog
 * 08.11.2012  Tim Ruehsen  created
 *
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>

#include <wget.h>
#include "private.h"

// Paul Larson's hash function from Microsoft Research
#ifdef __clang__
__attribute__((no_sanitize("integer")))
#endif
G_GNUC_WGET_PURE
static unsigned int hash_string(const char *key)
{
	unsigned int hash = 0; // use 0 as SALT if hash table attacks doesn't matter

	while (*key)
		hash = hash * 101 + (unsigned char)*key++;

	return hash;
}

#ifdef __clang__
__attribute__((no_sanitize("integer")))
#endif
G_GNUC_WGET_PURE
static unsigned int hash_string_nocase(const char *key)
{
	unsigned int hash = 0; // use 0 as SALT if hash table attacks doesn't matter

	while (*key)
		hash = hash * 101 + (unsigned char)tolower(*key++);

	return hash;
}

/**
 * \file
 * \brief Stringmap functions
 * \defgroup libwget-stringmap Stringmap functions
 * @{
 *
 * Stringmaps are key/value stores that perform at O(1) for insertion, searching and removing.
 * The key is a C string.
 *
 * These functions are a wrapper around the Hashmap API.
 */

/**
 * \param[in] max Initial number of pre-allocated entries
 * \return New stringmap instance
 *
 * Create a new stringmap instance with initial size \p max.
 * It should be free'd after use with wget_stringmap_free().
 *
 * The hash function is an efficient string hash algorithm originally researched by Paul Larson.
 *
 * The compare function is strcmp(). The key strings are compared case-sensitive.
 */
wget_stringmap_t *wget_stringmap_create(int max)
{
	return wget_hashmap_create(max, (wget_hashmap_hash_t)hash_string, (wget_hashmap_compare_t)wget_strcmp);
}

/**
 * \param[in] max Initial number of pre-allocated entries
 * \return New stringmap instance
 *
 * Create a new stringmap instance with initial size \p max.
 * It should be free'd after use with wget_stringmap_free().
 *
 * The hash function is an efficient string hash algorithm originally researched by Paul Larson, using
 * lowercase'd keys.
 *
 * The compare function is strcasecmp() (case-insensitive).
 */
wget_stringmap_t *wget_stringmap_create_nocase(int max)
{
	return wget_hashmap_create(max, (wget_hashmap_hash_t)hash_string_nocase, (wget_hashmap_compare_t)wget_strcasecmp);
}

/**
 * \param[in] h Stringmap to put data into
 * \param[in] key Key to insert into \p h
 * \param[in] value Value to insert into \p h
 * \return 0 if inserted a new entry, 1 if entry existed
 *
 * Insert a key/value pair into stringmap \p h.
 *
 * \p key and \p value are *not* cloned, the stringmap takes 'ownership' of both.
 *
 * If \p key already exists and the pointer values the old and the new key differ,
 * the old key will be destroyed by calling the key destructor function (default is free()).
 *
 * To realize a hashset (just keys without values), \p value may be %NULL.
 *
 * Neither \p h nor \p key must be %NULL.
 */
int wget_stringmap_put_noalloc(wget_stringmap_t *h, const char *key, const void *value)
{
	return wget_hashmap_put_noalloc(h, key, value);
}

/**
 * \param[in] h Stringmap to put data into
 * \param[in] key Key to insert into \p h
 * \param[in] value Value to insert into \p h
 * \param[in] valuesize Size of \p value
 * \return 0 if inserted a new entry, 1 if entry existed
 *
 * Insert a key/value pair into stringmap \p h.
 *
 * If \p key already exists it will not be cloned. In this case the value destructor function
 * will be called with the old value and the new value will be shallow cloned.
 *
 * If \p doesn't exist, both \p key and \p value will be shallow cloned.
 *
 * To realize a hashset (just keys without values), \p value may be %NULL.
 *
 * Neither \p h nor \p key must be %NULL.
 */
int wget_stringmap_put(wget_stringmap_t *h, const char *key, const void *value, size_t valuesize)
{
	return wget_hashmap_put(h, key, strlen(key) + 1, value, valuesize);
}

/**
 * \param[in] h Stringmap
 * \param[in] key Key to search for
 * \param[out] value Value to be returned
 * \return 1 if \p key has been found, 0 if not found
 *
 * Get the value for a given key.
 *
 * If there are %NULL values in the stringmap, you should use this function
 * to distinguish between 'not found' and 'found %NULL value'.
 *
 * Neither \p h nor \p key must be %NULL.
 */
int wget_stringmap_get_null(const wget_stringmap_t *h, const char *key, void **value)
{
	return wget_hashmap_get_null(h, key, value);
}

/**
 * \param[in] h Stringmap
 * \param[in] key Key to search for
 * \return Found value or %NULL if not found
 *
 * Get the value for a given key.
 *
 * If there are %NULL values in the stringmap, you should use wget_stringmap_get_null()
 * to distinguish between 'not found' and 'found %NULL value'.
 *
 * Neither \p h nor \p key must be %NULL.
 */
void *wget_stringmap_get(const wget_stringmap_t *h, const char *key)
{
	return wget_hashmap_get(h, key);
}

/**
 * \param[in] h Stringmap
 * \param[in] key Key to search for
 * \return 1 if \p key has been found, 0 if not found
 *
 * Check if \p key exists in \p h.
 */
int wget_stringmap_contains(const wget_stringmap_t *h, const char *key)
{
	return wget_hashmap_contains(h, key);
}

/**
 * \param[in] h Stringmap
 * \param[in] key Key to be removed
 * \return 1 if \p key has been removed, 0 if not found
 *
 * Remove \p key from stringmap \p h.
 *
 * If \p key is found, the key and value destructor functions are called
 * when removing the entry from the stringmap.
 */
int wget_stringmap_remove(wget_stringmap_t *h, const char *key)
{
	return wget_hashmap_remove(h, key);
}

/**
 * \param[in] h Stringmap
 * \param[in] key Key to be removed
 * \return 1 if \p key has been removed, 0 if not found
 *
 * Remove \p key from stringmap \p h.
 *
 * Key and value destructor functions are *not* called when removing the entry from the stringmap.
 */
int wget_stringmap_remove_nofree(wget_stringmap_t *h, const char *key)
{
	return wget_hashmap_remove(h, key);
}

/**
 * \param[in] h Stringmap to be free'd
 *
 * Remove all entries from stringmap \p h and free the stringmap instance.
 *
 * Key and value destructor functions are called for each entry in the stringmap.
 */
void wget_stringmap_free(wget_stringmap_t **h)
{
	wget_hashmap_free(h);
}

/**
 * \param[in] h Stringmap to be cleared
 *
 * Remove all entries from stringmap \p h.
 *
 * Key and value destructor functions are called for each entry in the stringmap.
 */
void wget_stringmap_clear(wget_stringmap_t *h)
{
	wget_hashmap_clear(h);
}

/**
 * \param[in] h Stringmap
 * \return Number of entries in stringmap \p h
 *
 * Return the number of entries in the stringmap \p h.
 */
int wget_stringmap_size(const wget_stringmap_t *h)
{
	return wget_hashmap_size(h);
}

/**
 * \param[in] h Stringmap
 * \param[in] browse Function to be called for each element of \p h
 * \param[in] ctx Context variable use as param to \p browse
 * \return Return value of the last call to \p browse
 *
 * Call function \p browse for each element of stringmap \p h or until \p browse
 * returns a value not equal to zero.
 *
 * \p browse is called with \p ctx and the pointer to the current element.
 *
 * The return value of the last call to \p browse is returned or 0 if either \p h or \p browse is %NULL.
 */
int wget_stringmap_browse(const wget_stringmap_t *h, wget_stringmap_browse_t browse, void *ctx)
{
	return wget_hashmap_browse(h, (wget_hashmap_browse_t)browse, ctx);
}

/**
 * \param[in] h Stringmap
 * \param[in] cmp Comparison function used to find keys
 *
 * Set the comparison function.
 */
void wget_stringmap_setcmpfunc(wget_stringmap_t *h, wget_stringmap_compare_t cmp)
{
	wget_hashmap_setcmpfunc(h, (wget_hashmap_compare_t)cmp);
}

/**
 * \param[in] h Stringmap
 * \param[in] hash Hash function used to hash keys
 *
 * Set the key hash function.
 *
 * The keys of all entries in the stringmap will be hashed again.
 */
void wget_stringmap_sethashfunc(wget_stringmap_t *h, wget_stringmap_hash_t hash)
{
	wget_hashmap_sethashfunc(h, (wget_hashmap_hash_t)hash);
}

/**
 * \param[in] h Stringmap
 * \param[in] destructor Destructor function for keys
 *
 * Set the key destructor function.
 *
 * Default is free().
 */
void wget_stringmap_set_key_destructor(wget_hashmap_t *h, wget_stringmap_key_destructor_t destructor)
{
	wget_hashmap_set_key_destructor(h, (wget_hashmap_key_destructor_t)destructor);
}

/**
 * \param[in] h Stringmap
 * \param[in] destructor Destructor function for values
 *
 * Set the value destructor function.
 *
 * Default is free().
 */
void wget_stringmap_set_value_destructor(wget_hashmap_t *h, wget_stringmap_value_destructor_t destructor)
{
	wget_hashmap_set_value_destructor(h, (wget_hashmap_value_destructor_t)destructor);
}

/**
 * \param[in] h Stringmap
 * \param[in] factor The load factor
 *
 * Set the load factor function.
 *
 * The load factor is determines when to resize the internal memory.
 * 0.75 means "resize if 75% or more of all slots are used".
 *
 * The resize strategy is set by wget_stringmap_set_growth_policy().
 *
 * The resize (and rehashing) occurs earliest on the next insertion of a new key.
 *
 * Default is 0.75.
 */
void wget_stringmap_setloadfactor(wget_stringmap_t *h, float factor)
{
	wget_hashmap_setloadfactor(h, factor);
}

/**
 * \param[in] h Stringmap
 * \param[in] off Stringmap growth mode:
 *   positive values: increase size by \p off entries on each resize
 *   negative values: increase size by multiplying \p -off, e.g. -2 doubles the size on each resize
 *
 * Set the growth policy for internal memory.
 *
 * Default is -2.
 */
void wget_stringmap_set_growth_policy(wget_stringmap_t *h, int off)
{
	wget_hashmap_set_growth_policy(h, off);
}

/**@}*/