NeoMutt  2025-12-11-694-ga89709
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
hash.c File Reference

Hash Table data structure. More...

#include "config.h"
#include <stdbool.h>
#include "hash.h"
#include "ctype2.h"
#include "memory.h"
#include "string2.h"
+ Include dependency graph for hash.c:

Go to the source code of this file.

Macros

#define SOME_PRIME   149711
 A prime number used for hashing.
 

Functions

static size_t gen_hash_string (union HashKey key, size_t num_elems)
 Generate a hash from a string - Implements hash_gen_hash_t -.
 
static int cmp_key_string (union HashKey a, union HashKey b)
 Compare two string keys - Implements hash_cmp_key_t -.
 
static size_t gen_hash_case_string (union HashKey key, size_t num_elems)
 Generate a hash from a string (ignore the case) - Implements hash_gen_hash_t -.
 
static int cmp_key_case_string (union HashKey a, union HashKey b)
 Compare two string keys (ignore case) - Implements hash_cmp_key_t -.
 
static size_t gen_hash_int (union HashKey key, size_t num_elems)
 Generate a hash from an integer - Implements hash_gen_hash_t -.
 
static int cmp_key_int (union HashKey a, union HashKey b)
 Compare two integer keys - Implements hash_cmp_key_t -.
 
static struct HashTablehash_new (size_t num_elems)
 Create a new Hash Table.
 
static struct HashElemunion_hash_insert (struct HashTable *table, union HashKey key, int type, void *data)
 Insert into a hash table using a union as a key.
 
static struct HashElemunion_hash_find_elem (const struct HashTable *table, union HashKey key)
 Find a HashElem in a Hash Table element using a key.
 
static void * union_hash_find (const struct HashTable *table, union HashKey key)
 Find the HashElem data in a Hash Table element using a key.
 
static void union_hash_delete (struct HashTable *table, union HashKey key, const void *data)
 Remove an element from a Hash Table.
 
struct HashTablemutt_hash_new (size_t num_elems, HashFlags flags)
 Create a new Hash Table (with string keys)
 
struct HashTablemutt_hash_int_new (size_t num_elems, HashFlags flags)
 Create a new Hash Table (with integer keys)
 
void mutt_hash_set_destructor (struct HashTable *table, hash_hdata_free_t fn, intptr_t fn_data)
 Set the destructor for a Hash Table.
 
struct HashElemmutt_hash_typed_insert (struct HashTable *table, const char *strkey, int type, void *data)
 Insert a string with type info into a Hash Table.
 
struct HashElemmutt_hash_insert (struct HashTable *table, const char *strkey, void *data)
 Add a new element to the Hash Table (with string keys)
 
struct HashElemmutt_hash_int_insert (struct HashTable *table, unsigned int intkey, void *data)
 Add a new element to the Hash Table (with integer keys)
 
void * mutt_hash_find (const struct HashTable *table, const char *strkey)
 Find the HashElem data in a Hash Table element using a key.
 
struct HashElemmutt_hash_find_elem (const struct HashTable *table, const char *strkey)
 Find the HashElem in a Hash Table element using a key.
 
void * mutt_hash_int_find (const struct HashTable *table, unsigned int intkey)
 Find the HashElem data in a Hash Table element using a key.
 
struct HashElemmutt_hash_find_bucket (const struct HashTable *table, const char *strkey)
 Find the HashElem in a Hash Table element using a key.
 
void mutt_hash_delete (struct HashTable *table, const char *strkey, const void *data)
 Remove an element from a Hash Table.
 
void mutt_hash_int_delete (struct HashTable *table, unsigned int intkey, const void *data)
 Remove an element from a Hash Table.
 
void mutt_hash_free (struct HashTable **ptr)
 Free a hash table.
 
struct HashElemmutt_hash_walk (const struct HashTable *table, struct HashWalkState *state)
 Iterate through all the HashElem's in a Hash Table.
 

Detailed Description

Hash Table data structure.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Thomas Klausner

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file hash.c.

Macro Definition Documentation

◆ SOME_PRIME

#define SOME_PRIME   149711

A prime number used for hashing.

Definition at line 39 of file hash.c.

Function Documentation

◆ hash_new()

static struct HashTable * hash_new ( size_t num_elems)
static

Create a new Hash Table.

Parameters
num_elemsNumber of elements it should contain
Return values
ptrNew Hash Table

The Hash Table can contain more elements than num_elems, but they will be chained together.

Definition at line 123 of file hash.c.

124{
125 struct HashTable *table = MUTT_MEM_CALLOC(1, struct HashTable);
126 if (num_elems == 0)
127 num_elems = 2;
128 table->num_elems = num_elems;
129 table->table = MUTT_MEM_CALLOC(num_elems, struct HashElem *);
130 return table;
131}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
The item stored in a Hash Table.
Definition hash.h:44
A Hash Table.
Definition hash.h:99
struct HashElem ** table
Array of Hash keys.
Definition hash.h:103
size_t num_elems
Number of buckets in the Hash Table.
Definition hash.h:100
+ Here is the caller graph for this function:

◆ union_hash_insert()

static struct HashElem * union_hash_insert ( struct HashTable * table,
union HashKey key,
int type,
void * data )
static

Insert into a hash table using a union as a key.

Parameters
tableHash Table to update
keyKey to hash on
typeData type
dataData to associate with key
Return values
ptrNewly inserted HashElem

Definition at line 141 of file hash.c.

143{
144 if (!table)
145 return NULL; // LCOV_EXCL_LINE
146
147 struct HashElem *he = MUTT_MEM_CALLOC(1, struct HashElem);
148 size_t hash = table->gen_hash(key, table->num_elems);
149 he->key = key;
150 he->data = data;
151 he->type = type;
152
153 if (table->allow_dups)
154 {
155 he->next = table->table[hash];
156 table->table[hash] = he;
157 }
158 else
159 {
160 struct HashElem *tmp = NULL, *last = NULL;
161
162 for (tmp = table->table[hash], last = NULL; tmp; last = tmp, tmp = tmp->next)
163 {
164 const int rc = table->cmp_key(tmp->key, key);
165 if (rc == 0)
166 {
167 FREE(&he);
168 return NULL;
169 }
170 if (rc > 0)
171 break;
172 }
173 if (last)
174 last->next = he;
175 else
176 table->table[hash] = he;
177 he->next = tmp;
178 }
179 return he;
180}
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
struct HashElem * next
Linked List.
Definition hash.h:48
union HashKey key
Key representing the data.
Definition hash.h:46
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
void * data
User-supplied data.
Definition hash.h:47
hash_gen_hash_t gen_hash
Function to generate hash id from the key.
Definition hash.h:104
hash_cmp_key_t cmp_key
Function to compare two Hash keys.
Definition hash.h:105
bool allow_dups
if set, duplicate keys are allowed
Definition hash.h:102
+ Here is the caller graph for this function:

◆ union_hash_find_elem()

static struct HashElem * union_hash_find_elem ( const struct HashTable * table,
union HashKey key )
static

Find a HashElem in a Hash Table element using a key.

Parameters
tableHash Table to search
keyKey (either string or integer)
Return values
ptrHashElem matching the key

Definition at line 188 of file hash.c.

189{
190 if (!table)
191 return NULL; // LCOV_EXCL_LINE
192
193 size_t hash = table->gen_hash(key, table->num_elems);
194 struct HashElem *he = table->table[hash];
195 for (; he; he = he->next)
196 {
197 if (table->cmp_key(key, he->key) == 0)
198 return he;
199 }
200 return NULL;
201}
+ Here is the caller graph for this function:

◆ union_hash_find()

static void * union_hash_find ( const struct HashTable * table,
union HashKey key )
static

Find the HashElem data in a Hash Table element using a key.

Parameters
tableHash Table to search
keyKey (either string or integer)
Return values
ptrData attached to the HashElem matching the key

Definition at line 209 of file hash.c.

210{
211 if (!table)
212 return NULL; // LCOV_EXCL_LINE
213 struct HashElem *he = union_hash_find_elem(table, key);
214 if (he)
215 return he->data;
216 return NULL;
217}
static struct HashElem * union_hash_find_elem(const struct HashTable *table, union HashKey key)
Find a HashElem in a Hash Table element using a key.
Definition hash.c:188
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ union_hash_delete()

static void union_hash_delete ( struct HashTable * table,
union HashKey key,
const void * data )
static

Remove an element from a Hash Table.

Parameters
tableHash Table to use
keyKey (either string or integer)
dataPrivate data to match (or NULL for any match)

Definition at line 225 of file hash.c.

226{
227 if (!table)
228 return; // LCOV_EXCL_LINE
229
230 size_t hash = table->gen_hash(key, table->num_elems);
231 struct HashElem *he = table->table[hash];
232 struct HashElem **he_last = &table->table[hash];
233
234 while (he)
235 {
236 if (((data == he->data) || !data) && (table->cmp_key(he->key, key) == 0))
237 {
238 *he_last = he->next;
239 if (table->hdata_free)
240 table->hdata_free(he->type, he->data, table->hdata);
241 if (table->strdup_keys)
242 FREE(&he->key.strkey);
243 FREE(&he);
244
245 he = *he_last;
246 }
247 else
248 {
249 he_last = &he->next;
250 he = he->next;
251 }
252 }
253}
bool strdup_keys
if set, the key->strkey is strdup()'d
Definition hash.h:101
intptr_t hdata
Data to pass to the hdata_free() function.
Definition hash.h:106
hash_hdata_free_t hdata_free
Function to free a Hash element.
Definition hash.h:107
const char * strkey
String key.
Definition hash.h:36
+ Here is the caller graph for this function:

◆ mutt_hash_new()

struct HashTable * mutt_hash_new ( size_t num_elems,
HashFlags flags )

Create a new Hash Table (with string keys)

Parameters
num_elemsNumber of elements it should contain
flagsFlags, see HashFlags
Return values
ptrNew Hash Table

Definition at line 261 of file hash.c.

262{
264 if (flags & MUTT_HASH_STRCASECMP)
265 {
266 table->gen_hash = gen_hash_case_string;
267 table->cmp_key = cmp_key_case_string;
268 }
269 else
270 {
271 table->gen_hash = gen_hash_string;
272 table->cmp_key = cmp_key_string;
273 }
274 if (flags & MUTT_HASH_STRDUP_KEYS)
275 table->strdup_keys = true;
276 if (flags & MUTT_HASH_ALLOW_DUPS)
277 table->allow_dups = true;
278 return table;
279}
static int cmp_key_case_string(union HashKey a, union HashKey b)
Compare two string keys (ignore case) - Implements hash_cmp_key_t -.
Definition hash.c:90
static int cmp_key_string(union HashKey a, union HashKey b)
Compare two string keys - Implements hash_cmp_key_t -.
Definition hash.c:63
static size_t gen_hash_string(union HashKey key, size_t num_elems)
Generate a hash from a string - Implements hash_gen_hash_t -.
Definition hash.c:46
static size_t gen_hash_case_string(union HashKey key, size_t num_elems)
Generate a hash from a string (ignore the case) - Implements hash_gen_hash_t -.
Definition hash.c:73
static struct HashTable * hash_new(size_t num_elems)
Create a new Hash Table.
Definition hash.c:123
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition hash.h:113
#define MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
Definition hash.h:114
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition hash.h:112
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_int_new()

struct HashTable * mutt_hash_int_new ( size_t num_elems,
HashFlags flags )

Create a new Hash Table (with integer keys)

Parameters
num_elemsNumber of elements it should contain
flagsFlags, see HashFlags
Return values
ptrNew Hash Table

Definition at line 287 of file hash.c.

288{
290 table->gen_hash = gen_hash_int;
291 table->cmp_key = cmp_key_int;
292 if (flags & MUTT_HASH_ALLOW_DUPS)
293 table->allow_dups = true;
294 return table;
295}
static int cmp_key_int(union HashKey a, union HashKey b)
Compare two integer keys - Implements hash_cmp_key_t -.
Definition hash.c:106
static size_t gen_hash_int(union HashKey key, size_t num_elems)
Generate a hash from an integer - Implements hash_gen_hash_t -.
Definition hash.c:98
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_set_destructor()

void mutt_hash_set_destructor ( struct HashTable * table,
hash_hdata_free_t fn,
intptr_t fn_data )

Set the destructor for a Hash Table.

Parameters
tableHash Table to use
fnCallback function to free Hash Table's resources
fn_dataData to pass to the callback function

Definition at line 303 of file hash.c.

304{
305 if (!table)
306 return;
307 table->hdata_free = fn;
308 table->hdata = fn_data;
309}
+ Here is the caller graph for this function:

◆ mutt_hash_typed_insert()

struct HashElem * mutt_hash_typed_insert ( struct HashTable * table,
const char * strkey,
int type,
void * data )

Insert a string with type info into a Hash Table.

Parameters
tableHash Table to use
strkeyString key
typeType to associate with the key
dataPrivate data associated with the key
Return values
ptrNewly inserted HashElem

Definition at line 319 of file hash.c.

321{
322 if (!table || !strkey)
323 return NULL;
324
325 union HashKey key;
326 key.strkey = table->strdup_keys ? mutt_str_dup(strkey) : strkey;
327 return union_hash_insert(table, key, type, data);
328}
static struct HashElem * union_hash_insert(struct HashTable *table, union HashKey key, int type, void *data)
Insert into a hash table using a union as a key.
Definition hash.c:141
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
The data item stored in a HashElem.
Definition hash.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_insert()

struct HashElem * mutt_hash_insert ( struct HashTable * table,
const char * strkey,
void * data )

Add a new element to the Hash Table (with string keys)

Parameters
tableHash Table (with string keys)
strkeyString key
dataPrivate data associated with the key
Return values
ptrNewly inserted HashElem

Definition at line 337 of file hash.c.

338{
339 return mutt_hash_typed_insert(table, strkey, -1, data);
340}
struct HashElem * mutt_hash_typed_insert(struct HashTable *table, const char *strkey, int type, void *data)
Insert a string with type info into a Hash Table.
Definition hash.c:319
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_int_insert()

struct HashElem * mutt_hash_int_insert ( struct HashTable * table,
unsigned int intkey,
void * data )

Add a new element to the Hash Table (with integer keys)

Parameters
tableHash Table (with integer keys)
intkeyInteger key
dataPrivate data associated with the key
Return values
ptrNewly inserted HashElem

Definition at line 349 of file hash.c.

350{
351 if (!table)
352 return NULL;
353 union HashKey key;
354 key.intkey = intkey;
355 return union_hash_insert(table, key, -1, data);
356}
unsigned int intkey
Integer key.
Definition hash.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_find()

void * mutt_hash_find ( const struct HashTable * table,
const char * strkey )

Find the HashElem data in a Hash Table element using a key.

Parameters
tableHash Table to search
strkeyString key to search for
Return values
ptrData attached to the HashElem matching the key

Definition at line 364 of file hash.c.

365{
366 if (!table || !strkey)
367 return NULL;
368 union HashKey key;
369 key.strkey = strkey;
370 return union_hash_find(table, key);
371}
static void * union_hash_find(const struct HashTable *table, union HashKey key)
Find the HashElem data in a Hash Table element using a key.
Definition hash.c:209
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_find_elem()

struct HashElem * mutt_hash_find_elem ( const struct HashTable * table,
const char * strkey )

Find the HashElem in a Hash Table element using a key.

Parameters
tableHash Table to search
strkeyString key to search for
Return values
ptrHashElem matching the key

Definition at line 379 of file hash.c.

380{
381 if (!table || !strkey)
382 return NULL;
383 union HashKey key;
384 key.strkey = strkey;
385 return union_hash_find_elem(table, key);
386}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_int_find()

void * mutt_hash_int_find ( const struct HashTable * table,
unsigned int intkey )

Find the HashElem data in a Hash Table element using a key.

Parameters
tableHash Table to search
intkeyInteger key
Return values
ptrData attached to the HashElem matching the key

Definition at line 394 of file hash.c.

395{
396 if (!table)
397 return NULL;
398 union HashKey key;
399 key.intkey = intkey;
400 return union_hash_find(table, key);
401}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_find_bucket()

struct HashElem * mutt_hash_find_bucket ( const struct HashTable * table,
const char * strkey )

Find the HashElem in a Hash Table element using a key.

Parameters
tableHash Table to search
strkeyString key to search for
Return values
ptrHashElem matching the key

Unlike mutt_hash_find_elem(), this will return the first matching entry.

Definition at line 411 of file hash.c.

412{
413 if (!table || !strkey)
414 return NULL;
415
416 union HashKey key;
417
418 key.strkey = strkey;
419 size_t hash = table->gen_hash(key, table->num_elems);
420 return table->table[hash];
421}
+ Here is the caller graph for this function:

◆ mutt_hash_delete()

void mutt_hash_delete ( struct HashTable * table,
const char * strkey,
const void * data )

Remove an element from a Hash Table.

Parameters
tableHash Table to use
strkeyString key to match
dataPrivate data to match (or NULL for any match)

Definition at line 429 of file hash.c.

430{
431 if (!table || !strkey || (strkey[0] == '\0'))
432 return;
433 union HashKey key;
434 // Copy the key because union_hash_delete() may use it after the HashElem is freed.
436 union_hash_delete(table, key, data);
437 FREE(&key.strkey);
438}
static void union_hash_delete(struct HashTable *table, union HashKey key, const void *data)
Remove an element from a Hash Table.
Definition hash.c:225
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_int_delete()

void mutt_hash_int_delete ( struct HashTable * table,
unsigned int intkey,
const void * data )

Remove an element from a Hash Table.

Parameters
tableHash Table to use
intkeyInteger key to match
dataPrivate data to match (or NULL for any match)

Definition at line 446 of file hash.c.

447{
448 if (!table)
449 return;
450 union HashKey key;
451 key.intkey = intkey;
452 union_hash_delete(table, key, data);
453}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hash_free()

void mutt_hash_free ( struct HashTable ** ptr)

Free a hash table.

Parameters
[out]ptrHash Table to be freed

Definition at line 459 of file hash.c.

460{
461 if (!ptr || !*ptr)
462 return;
463
464 struct HashTable *table = *ptr;
465 struct HashElem *he = NULL, *tmp = NULL;
466
467 for (size_t i = 0; i < table->num_elems; i++)
468 {
469 for (he = table->table[i]; he;)
470 {
471 tmp = he;
472 he = he->next;
473 if (table->hdata_free && tmp->data)
474 table->hdata_free(tmp->type, tmp->data, table->hdata);
475 if (table->strdup_keys)
476 FREE(&tmp->key.strkey);
477 FREE(&tmp);
478 }
479 }
480 FREE(&table->table);
481 FREE(ptr);
482}
+ Here is the caller graph for this function:

◆ mutt_hash_walk()

struct HashElem * mutt_hash_walk ( const struct HashTable * table,
struct HashWalkState * state )

Iterate through all the HashElem's in a Hash Table.

Parameters
tableHash Table to search
stateCursor to keep track
Return values
ptrNext HashElem in the Hash Table
NULLWhen the last HashElem has been seen

Definition at line 491 of file hash.c.

492{
493 if (!table || !state)
494 return NULL;
495
496 if (state->last && state->last->next)
497 {
498 state->last = state->last->next;
499 return state->last;
500 }
501
502 if (state->last)
503 state->index++;
504
505 while (state->index < table->num_elems)
506 {
507 if (table->table[state->index])
508 {
509 state->last = table->table[state->index];
510 return state->last;
511 }
512 state->index++;
513 }
514
515 state->index = 0;
516 state->last = NULL;
517 return NULL;
518}
size_t index
Current position in table.
Definition hash.h:135
struct HashElem * last
Current element in linked list.
Definition hash.h:136
+ Here is the caller graph for this function: