NeoMutt  2025-12-11-980-ge38c27
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;
161 struct HashElem *last = NULL;
162
163 for (tmp = table->table[hash], last = NULL; tmp; last = tmp, tmp = tmp->next)
164 {
165 const int rc = table->cmp_key(tmp->key, key);
166 if (rc == 0)
167 {
168 FREE(&he);
169 return NULL;
170 }
171 if (rc > 0)
172 break;
173 }
174 if (last)
175 last->next = he;
176 else
177 table->table[hash] = he;
178 he->next = tmp;
179 }
180 return he;
181}
#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 189 of file hash.c.

190{
191 if (!table)
192 return NULL; // LCOV_EXCL_LINE
193
194 size_t hash = table->gen_hash(key, table->num_elems);
195 struct HashElem *he = table->table[hash];
196 for (; he; he = he->next)
197 {
198 if (table->cmp_key(key, he->key) == 0)
199 return he;
200 }
201 return NULL;
202}
+ 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 210 of file hash.c.

211{
212 if (!table)
213 return NULL; // LCOV_EXCL_LINE
214 struct HashElem *he = union_hash_find_elem(table, key);
215 if (he)
216 return he->data;
217 return NULL;
218}
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:189
+ 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 226 of file hash.c.

227{
228 if (!table)
229 return; // LCOV_EXCL_LINE
230
231 size_t hash = table->gen_hash(key, table->num_elems);
232 struct HashElem *he = table->table[hash];
233 struct HashElem **he_last = &table->table[hash];
234
235 while (he)
236 {
237 if (((data == he->data) || !data) && (table->cmp_key(he->key, key) == 0))
238 {
239 *he_last = he->next;
240 if (table->hdata_free)
241 table->hdata_free(he->type, he->data, table->hdata);
242 if (table->strdup_keys)
243 FREE(&he->key.strkey);
244 FREE(&he);
245
246 he = *he_last;
247 }
248 else
249 {
250 he_last = &he->next;
251 he = he->next;
252 }
253 }
254}
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 262 of file hash.c.

263{
265 if (flags & MUTT_HASH_STRCASECMP)
266 {
267 table->gen_hash = gen_hash_case_string;
268 table->cmp_key = cmp_key_case_string;
269 }
270 else
271 {
272 table->gen_hash = gen_hash_string;
273 table->cmp_key = cmp_key_string;
274 }
275 if (flags & MUTT_HASH_STRDUP_KEYS)
276 table->strdup_keys = true;
277 if (flags & MUTT_HASH_ALLOW_DUPS)
278 table->allow_dups = true;
279 return table;
280}
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
@ MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
Definition hash.h:118
@ MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition hash.h:116
@ MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition hash.h:117
+ 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 288 of file hash.c.

289{
291 table->gen_hash = gen_hash_int;
292 table->cmp_key = cmp_key_int;
293 if (flags & MUTT_HASH_ALLOW_DUPS)
294 table->allow_dups = true;
295 return table;
296}
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 304 of file hash.c.

305{
306 if (!table)
307 return;
308 table->hdata_free = fn;
309 table->hdata = fn_data;
310}
+ 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 320 of file hash.c.

322{
323 if (!table || !strkey)
324 return NULL;
325
326 union HashKey key = { 0 };
327 key.strkey = table->strdup_keys ? mutt_str_dup(strkey) : strkey;
328 return union_hash_insert(table, key, type, data);
329}
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 338 of file hash.c.

339{
340 return mutt_hash_typed_insert(table, strkey, -1, data);
341}
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:320
+ 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 350 of file hash.c.

351{
352 if (!table)
353 return NULL;
354 union HashKey key = { 0 };
355 key.intkey = intkey;
356 return union_hash_insert(table, key, -1, data);
357}
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 365 of file hash.c.

366{
367 if (!table || !strkey)
368 return NULL;
369 union HashKey key = { 0 };
370 key.strkey = strkey;
371 return union_hash_find(table, key);
372}
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:210
+ 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 380 of file hash.c.

381{
382 if (!table || !strkey)
383 return NULL;
384 union HashKey key = { 0 };
385 key.strkey = strkey;
386 return union_hash_find_elem(table, key);
387}
+ 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 395 of file hash.c.

396{
397 if (!table)
398 return NULL;
399 union HashKey key = { 0 };
400 key.intkey = intkey;
401 return union_hash_find(table, key);
402}
+ 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 412 of file hash.c.

413{
414 if (!table || !strkey)
415 return NULL;
416
417 union HashKey key = { 0 };
418
419 key.strkey = strkey;
420 size_t hash = table->gen_hash(key, table->num_elems);
421 return table->table[hash];
422}
+ 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 430 of file hash.c.

431{
432 if (!table || !strkey || (strkey[0] == '\0'))
433 return;
434 union HashKey key = { 0 };
435 // Copy the key because union_hash_delete() may use it after the HashElem is freed.
437 union_hash_delete(table, key, data);
438 FREE(&key.strkey);
439}
static void union_hash_delete(struct HashTable *table, union HashKey key, const void *data)
Remove an element from a Hash Table.
Definition hash.c:226
+ 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 447 of file hash.c.

448{
449 if (!table)
450 return;
451 union HashKey key = { 0 };
452 key.intkey = intkey;
453 union_hash_delete(table, key, data);
454}
+ 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 460 of file hash.c.

461{
462 if (!ptr || !*ptr)
463 return;
464
465 struct HashTable *table = *ptr;
466 struct HashElem *he = NULL;
467 struct HashElem *tmp = NULL;
468
469 for (size_t i = 0; i < table->num_elems; i++)
470 {
471 for (he = table->table[i]; he;)
472 {
473 tmp = he;
474 he = he->next;
475 if (table->hdata_free && tmp->data)
476 table->hdata_free(tmp->type, tmp->data, table->hdata);
477 if (table->strdup_keys)
478 FREE(&tmp->key.strkey);
479 FREE(&tmp);
480 }
481 }
482 FREE(&table->table);
483 FREE(ptr);
484}
+ 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 493 of file hash.c.

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