libamxc  1.10.3
C Generic Data Containers
Hash Table
Collaboration diagram for Hash Table:

Modules

 Hash Table Iterator
 

Data Structures

struct  _amxc_htable
 The hash table structure. More...
 

Macros

#define amxc_htable_for_each(it, htable)
 Loops over items in the hash table. More...
 
#define amxc_htable_iterate(it, htable)
 Loops over items in the hash table. More...
 
#define AMXC_HTABLE_RANGE   UINT32_MAX
 Out of range indicator. More...
 

Typedefs

typedef unsigned int(* amxc_htable_hash_func_t) (const char *key, const unsigned int len)
 Definition of the hash function. More...
 
typedef void(* amxc_htable_it_delete_t) (const char *key, amxc_htable_it_t *it)
 Definition of the hash table item delete function. More...
 
typedef struct _amxc_htable amxc_htable_t
 The hash table structure. More...
 

Functions

int amxc_htable_new (amxc_htable_t **htable, const size_t reserve)
 Allocates a hash table. More...
 
void amxc_htable_delete (amxc_htable_t **htable, amxc_htable_it_delete_t func)
 Frees the previously allocated hash table. More...
 
int amxc_htable_init (amxc_htable_t *const htable, const size_t reserve)
 Initializes a hash table. More...
 
void amxc_htable_clean (amxc_htable_t *const htable, amxc_htable_it_delete_t func)
 Removes all items from the hash table. More...
 
void amxc_htable_set_hash_func (amxc_htable_t *const htable, amxc_htable_hash_func_t func)
 Sets the hash function for the hash table. More...
 
unsigned int amxc_htable_key2index (const amxc_htable_t *const htable, const char *const key)
 Converts a key into an index. More...
 
AMXC_INLINE bool amxc_htable_is_empty (const amxc_htable_t *const htable)
 Checks that the hash table is empty. More...
 
AMXC_INLINE size_t amxc_htable_size (const amxc_htable_t *const htable)
 Calculates the size of the hash table. More...
 
AMXC_INLINE size_t amxc_htable_capacity (const amxc_htable_t *const htable)
 Calculates the capacity of the hash table. More...
 
int amxc_htable_insert (amxc_htable_t *const htable, const char *const key, amxc_htable_it_t *const it)
 Inserts an item in the hash table. More...
 
amxc_htable_it_tamxc_htable_get (const amxc_htable_t *const htable, const char *const key)
 Gets a hash table iterator from the hash table. More...
 
amxc_htable_it_tamxc_htable_take (amxc_htable_t *const htable, const char *const key)
 Removes a hash table iterator from the hash table. More...
 
amxc_htable_it_tamxc_htable_get_first (const amxc_htable_t *const htable)
 Gets the first item stored in the table. More...
 
amxc_htable_it_tamxc_htable_get_last (const amxc_htable_t *const htable)
 Gets the last item stored in the table. More...
 
amxc_array_tamxc_htable_get_sorted_keys (const amxc_htable_t *const htable)
 Creates an array containing all keys of the hash table. More...
 
AMXC_INLINE bool amxc_htable_contains (const amxc_htable_t *const htable, const char *const key)
 Verifies that a key is in the hash table. More...
 
int amxc_htable_move (amxc_htable_t *const dest, amxc_htable_t *const src)
 Moves all items from one hash table to another hash table. More...
 
AMXC_INLINE amxc_htable_it_tamxc_htable_take_first (const amxc_htable_t *const htable)
 Removes the first item stored in the table. More...
 

Detailed Description

Macro Definition Documentation

◆ amxc_htable_for_each

#define amxc_htable_for_each (   it,
  htable 
)
Value:
* it ## _next = amxc_htable_it_get_next(it); \
it; \
it = it ## _next, \
it ## _next = amxc_htable_it_get_next(it))
amxc_htable_it_t * amxc_htable_it_get_next(const amxc_htable_it_t *const reference)
Gets the next iterator in the hash table.
amxc_htable_it_t * amxc_htable_get_first(const amxc_htable_t *const htable)
Gets the first item stored in the table.
Definition: amxc_htable.c:313
The hash table iterator structure.
Definition: amxc_htable.h:138
static amxc_htable_it_t it[2000]
static amxc_htable_t * htable

Loops over items in the hash table.

Iterates over the hash table and updates the iterator each time.

Warning
Do not modify the hash table itself while using this macro. It is possible to nest this macro It is allowed to delete or remove the current iterator from the hash table.

Definition at line 102 of file amxc_htable.h.

◆ amxc_htable_iterate

#define amxc_htable_iterate (   it,
  htable 
)
Value:

Loops over items in the hash table.

Iterates over the hash table and updates the iterator each time.

Warning
Do not modify the hash table itself while using this macro.

Definition at line 119 of file amxc_htable.h.

◆ AMXC_HTABLE_RANGE

#define AMXC_HTABLE_RANGE   UINT32_MAX

Out of range indicator.

Definition at line 129 of file amxc_htable.h.

Typedef Documentation

◆ amxc_htable_hash_func_t

typedef unsigned int(* amxc_htable_hash_func_t) (const char *key, const unsigned int len)

Definition of the hash function.

The hash function calculates a hash from the key. A custom hash function can be implemented and set on the hash table using amxc_htable_set_hash_func.

A set of hash functions is already available in see amxc_hash.h.

The calculated hash is used to calculate the index of the position of the key in the array.

Definition at line 158 of file amxc_htable.h.

◆ amxc_htable_it_delete_t

typedef void(* amxc_htable_it_delete_t) (const char *key, amxc_htable_it_t *it)

Definition of the hash table item delete function.

A pointer to a delete function is used in the following functions amxc_htable_delete, amxc_htable_clean, amxc_htable_it_clean.

Definition at line 168 of file amxc_htable.h.

◆ amxc_htable_t

typedef struct _amxc_htable amxc_htable_t

The hash table structure.

Function Documentation

◆ amxc_htable_capacity()

AMXC_INLINE size_t amxc_htable_capacity ( const amxc_htable_t *const  htable)

Calculates the capacity of the hash table.

The capacity is the number of items that is reserved

Parameters
htablea pointer to the hash table structure
Returns
returns the number of reserved item positions in hash table

Definition at line 351 of file amxc_htable.h.

351  {
352  return htable != NULL ? htable->table.items : 0;
353 }
size_t items
Definition: amxc_array.h:163
amxc_array_t table
Definition: amxc_htable.h:176

◆ amxc_htable_clean()

void amxc_htable_clean ( amxc_htable_t *const  htable,
amxc_htable_it_delete_t  func 
)

Removes all items from the hash table.

Removes all items from the hash table, if a delete function is provided, it is called for each item after it was removed from the table. The buffer used to store the items is freed as well.

Parameters
htablea pointer to the htable structure
funcpointer to a function that is called to free each item in the hash table

Definition at line 200 of file amxc_htable.c.

200  {
201  when_null(htable, exit);
202 
203  htable->it_del = func;
205  htable->items = 0;
206 
207 exit:
208  return;
209 }
static void amxc_htable_it_delete_func(amxc_array_it_t *const it)
Definition: amxc_htable.c:131
#define when_null(x, l)
Definition: amxc_macros.h:126
void amxc_array_clean(amxc_array_t *const array, amxc_array_it_delete_t func)
Removes all items from the array.
Definition: amxc_array.c:261
size_t items
Definition: amxc_htable.h:177
amxc_htable_it_delete_t it_del
Definition: amxc_htable.h:179

◆ amxc_htable_contains()

AMXC_INLINE bool amxc_htable_contains ( const amxc_htable_t *const  htable,
const char *const  key 
)

Verifies that a key is in the hash table.

Parameters
htablea pointer to the hash table structure
keythe key
Returns
True when the key is at least once found in the table, false otherwise.

Definition at line 512 of file amxc_htable.h.

512  {
513  return amxc_htable_get(htable, key) ? true : false;
514 }
amxc_htable_it_t * amxc_htable_get(const amxc_htable_t *const htable, const char *const key)
Gets a hash table iterator from the hash table.
Definition: amxc_htable.c:278

◆ amxc_htable_delete()

void amxc_htable_delete ( amxc_htable_t **  htable,
amxc_htable_it_delete_t  func 
)

Frees the previously allocated hash table.

Removes all items from the hash table, if a delete function is provided, it is called for each item after it was removed from the hash table.

Frees the allocated memory and sets the pointer to NULL.

Note
Only call this function for hash tables that are allocated on the heap using amxc_htable_new
Parameters
htablea pointer to the location where the pointer to the hash table is be stored
funcpointer to a function that is called to free each item in the hash table

Definition at line 172 of file amxc_htable.c.

172  {
173  when_null(htable, exit);
174  when_null(*htable, exit);
175 
176  (*htable)->it_del = func;
177  amxc_array_clean(&(*htable)->table, amxc_htable_it_delete_func);
178  free(*htable);
179  *htable = NULL;
180 
181 exit:
182  return;
183 }

◆ amxc_htable_get()

amxc_htable_it_t* amxc_htable_get ( const amxc_htable_t *const  htable,
const char *const  key 
)

Gets a hash table iterator from the hash table.

The key provided is converted into an index using amxc_htable_key2index. If multiple items are available at the calculated position with the same key, the first one is returned. The next item can be retrieved with amxc_htable_it_get_next or with amxc_htable_it_get_next_key if it must have the same key.

Note
The item is not removed from the hash table. To remove the item use amxc_htable_take
Parameters
htablea pointer to the hash table structure
keythe item key
Returns
Pointer to the hash table iterator or NULL if no iterator was stored with the given key. The pointer can be converted to the real data pointer using amxc_htable_it_get_data

Definition at line 278 of file amxc_htable.c.

279  {
280  amxc_htable_it_t* it = NULL;
281  unsigned int index = 0;
282  amxc_array_it_t* ait = NULL;
283 
284  when_null(htable, exit);
285  when_null(key, exit);
286  when_true(*key == 0, exit);
287 
288  when_true(htable->table.items == 0, exit);
289 
290  index = amxc_htable_key2index(htable, key);
291  // the index is always in array bounderies.
292  // the following line is always returning a valid array iterator pointer
293  ait = amxc_array_get_at(&htable->table, index);
294 
295  it = ait == NULL? NULL:(amxc_htable_it_t*) ait->data;
296  while(it != NULL && strcmp(key, it->key) != 0) {
297  it = it->next;
298  }
299 
300 exit:
301  return it;
302 }
#define when_true(x, l)
Definition: amxc_macros.h:134
amxc_array_it_t * amxc_array_get_at(const amxc_array_t *const array, const unsigned int index)
Gets the item iterator for the given index.
Definition: amxc_array.c:504
unsigned int amxc_htable_key2index(const amxc_htable_t *const htable, const char *const key)
Converts a key into an index.
Definition: amxc_htable.c:225
The array iterator structure.
Definition: amxc_array.h:174
amxc_htable_it_t * next
Definition: amxc_htable.h:141

◆ amxc_htable_get_first()

amxc_htable_it_t* amxc_htable_get_first ( const amxc_htable_t *const  htable)

Gets the first item stored in the table.

This function iterates the table from the beginning and returns the first item encounter.

Note
The order of the items in the table is not the same as the order they were inserted in the table. So the first item found can be different then the first item inserted.
Parameters
htablea pointer to the hash table structure
Returns
Pointer to the hash table iterator or NULL if no items were stored in the hash table.

Definition at line 313 of file amxc_htable.c.

313  {
314  amxc_htable_it_t* it = NULL;
315  amxc_array_it_t* ait = NULL;
316  when_null(htable, exit);
317 
319  when_null(ait, exit);
320  it = (amxc_htable_it_t*) ait->data;
321 
322 exit:
323  return it;
324 }
amxc_array_it_t * amxc_array_get_first(const amxc_array_t *const array)
Gets the item iterator of the first used item in the array.
Definition: amxc_array.c:517

◆ amxc_htable_get_last()

amxc_htable_it_t* amxc_htable_get_last ( const amxc_htable_t *const  htable)

Gets the last item stored in the table.

This function iterates the table from the end and returns the last item encounter.

Note
The order of the items in the table is not the same as the order they were inserted in the table. So the last item found can be different then the last item inserted.
Parameters
htablea pointer to the hash table structure
Returns
Pointer to the hash table iterator or NULL if no items were stored in the hash table.

Definition at line 326 of file amxc_htable.c.

326  {
327  amxc_htable_it_t* it = NULL;
328  amxc_array_it_t* ait = NULL;
329  when_null(htable, exit);
330 
332  when_null(ait, exit);
333  it = (amxc_htable_it_t*) ait->data;
334 
335 exit:
336  return it;
337 }
amxc_array_it_t * amxc_array_get_last(const amxc_array_t *const array)
Gets the item iterator of the last used item in the array.
Definition: amxc_array.c:546

◆ amxc_htable_get_sorted_keys()

amxc_array_t* amxc_htable_get_sorted_keys ( const amxc_htable_t *const  htable)

Creates an array containing all keys of the hash table.

The array will be sorted in ascending order. If the hash table contains duplicate keys, the sorted array will contain duplicate keys as well.

The array will not contain empty items and the size is matching the number of items in the hash table.

The returned array should be deleted when not used anymore using amxc_array_delete, no delete function is needed.

Warning
Never delete the strings in the array, as these strings are no copies of the keys in the hash table. The array contains pointers to the keys in the hash table. Deleting them will render the hash table unusable and could lead to undefined behavior.
Parameters
htablea pointer to the hash table structure
Returns
A pointer to an amxc_array_t or NULL when the hash table is empty.

Definition at line 339 of file amxc_htable.c.

339  {
340  amxc_array_t* keys = NULL;
341  uint32_t size = 0;
342  uint32_t index = 0;
343  when_null(htable, exit);
344 
345  size = amxc_htable_size(htable);
346  when_true(size == 0, exit);
347 
348  amxc_array_new(&keys, size);
349  when_null(keys, exit);
350 
352  const char* key = amxc_htable_it_get_key(it);
353  amxc_array_set_data_at(keys, index, (void*) key);
354  index++;
355  }
356 
358 
359 exit:
360  return keys;
361 }
static int amxc_htable_cmp_keys(amxc_array_it_t *it1, amxc_array_it_t *it2)
Definition: amxc_htable.c:165
amxc_array_it_t * amxc_array_set_data_at(amxc_array_t *const array, const unsigned int index, void *data)
Sets data at the given index.
Definition: amxc_array.c:474
int8_t amxc_array_new(amxc_array_t **array, const size_t items)
Allocates an array.
Definition: amxc_array.c:179
int amxc_array_sort(amxc_array_t *const array, amxc_array_it_cmp_t cmp)
Sorts the content of the array.
Definition: amxc_array.c:596
AMXC_INLINE const char * amxc_htable_it_get_key(const amxc_htable_it_t *const it)
Gets the key from the iterator.
Definition: amxc_htable.h:672
AMXC_INLINE size_t amxc_htable_size(const amxc_htable_t *const htable)
Calculates the size of the hash table.
Definition: amxc_htable.h:334
#define amxc_htable_for_each(it, htable)
Loops over items in the hash table.
Definition: amxc_htable.h:102
The array structure.
Definition: amxc_array.h:162

◆ amxc_htable_init()

int amxc_htable_init ( amxc_htable_t *const  htable,
const size_t  reserve 
)

Initializes a hash table.

Initializes the hash table structure. All pointers are reset to NULL. This function is typically called for hash tables that are on the stack. Allocating and initializing a hash table on the heap can be done using amxc_htable_new

Note
When calling this function on an already initialized hash table, that contains items, the hash table is reset and all items in the table are lost (Could potentially lead to memory leaks). Use amxc_htable_clean to remove all items from the table.
Parameters
htablea pointer to the hash table structure.
reserveNumber of items that needs to be reserved
Returns
0 on success. -1 if a NULL pointer is given.

Definition at line 185 of file amxc_htable.c.

185  {
186  int retval = -1;
187  when_null(htable, exit);
188 
189  htable->items = 0;
191 
192  when_failed(amxc_array_init(&htable->table, reserve != 0 ? reserve : 64), exit);
193 
194  retval = 0;
195 
196 exit:
197  return retval;
198 }
#define when_failed(x, l)
Definition: amxc_macros.h:142
int amxc_array_init(amxc_array_t *const array, const size_t items)
Initializes an array.
Definition: amxc_array.c:231
unsigned int amxc_BKDR_hash(const char *str, const unsigned int len)
Calculate a hash from a string.
amxc_htable_hash_func_t hfunc
Definition: amxc_htable.h:178

◆ amxc_htable_insert()

int amxc_htable_insert ( amxc_htable_t *const  htable,
const char *const  key,
amxc_htable_it_t *const  it 
)

Inserts an item in the hash table.

The key provided is converted into an index using amxc_htable_key2index. When an position is already taken the items on that position are chained. The same key can be used for different items. When the number of items in the hash table is above 75% of the capacity, the table grows. The number of items that are reserved will be doubled with a maximum of 1024 items each time.

Parameters
htablea pointer to the hash table structure
keythe item key
itthe item htable iterator
Returns
0 when the item is inserted, -1 when an error occured

Definition at line 237 of file amxc_htable.c.

239  {
240  int retval = -1;
241 
242  when_null(htable, exit);
243  when_null(key, exit);
244  when_true(*key == 0, exit);
245  when_null(it, exit);
246 
247  // remove the iterator first
249  // no side effects here, strcmp does not modify the content of the string
250  // for performance reasons the pointer check is done first
251  if((it->key != NULL) && (strcmp(it->key, key) != 0)) {
252  free(it->key);
253  it->key = NULL;
254  }
255 
256  if((htable->table.items == 0) ||
257  (((htable->items + 1) * 100) / htable->table.items >= 75)) {
258  // time to grow the table
260  }
261 
262  // update htable iterator
263  if(it->key == NULL) {
264  size_t length = strlen(key);
265  it->key = (char*) calloc(length + 1, sizeof(char));
266  when_null(it->key, exit);
267  memcpy(it->key, key, length);
268  }
269 
271 
272  retval = 0;
273 
274 exit:
275  return retval;
276 }
static void amxc_htable_insert_it(amxc_htable_t *const htable, amxc_htable_it_t *const it)
Definition: amxc_htable.c:68
static int amxc_htable_grow(amxc_htable_t *const htable, size_t hint)
Definition: amxc_htable.c:85
void amxc_htable_it_take(amxc_htable_it_t *const it)
Removes the iterator from the hash table.

◆ amxc_htable_is_empty()

AMXC_INLINE bool amxc_htable_is_empty ( const amxc_htable_t *const  htable)

Checks that the hash table is empty.

Parameters
htablea pointer to the hash table structure
Returns
returns true when the hash table contains no items, false when there is at least one item in the table.

Definition at line 311 of file amxc_htable.h.

311  {
312  return htable != NULL ? (htable->items == 0) : true;
313 }

◆ amxc_htable_key2index()

unsigned int amxc_htable_key2index ( const amxc_htable_t *const  htable,
const char *const  key 
)

Converts a key into an index.

This function converts a key into an index using the hash function and the reserved size of the table

Parameters
htablea pointer to the htable structure
keythe key for which an index must be calculated
Returns
The calculated index or AMXC_HTABLE_RANGE if no reserved items are available in the table

Definition at line 225 of file amxc_htable.c.

226  {
227  unsigned int hash = AMXC_HTABLE_RANGE;
228  when_null(htable, exit);
229  when_true(htable->table.items == 0, exit);
230 
231  hash = htable->hfunc(key, strlen(key)) % htable->table.items;
232 
233 exit:
234  return hash;
235 }
#define AMXC_HTABLE_RANGE
Out of range indicator.
Definition: amxc_htable.h:129

◆ amxc_htable_move()

int amxc_htable_move ( amxc_htable_t *const  dest,
amxc_htable_t *const  src 
)

Moves all items from one hash table to another hash table.

After the move the source hash table will be empty.

If the destination hash table already contained items, the items of the source hash table are added to the destination.

Note
if moving fails, the source is not changed and the destination will be an ampty hash table
Parameters
desta pointer to the destination hash table structure
srca pointer to the source hash table structure
Returns
0 on success any other return value indicates failure.

Definition at line 363 of file amxc_htable.c.

363  {
364  int retval = -1;
365  size_t needed_items = 0;
366  size_t needed_cap = 0;
367  size_t dest_cap = 0;
368 
369  when_null(dest, exit);
370  when_null(src, exit);
371 
372  needed_items = amxc_htable_size(src) + amxc_htable_size(dest);
373  needed_cap = ((needed_items + 1) * 100) / 75;
374  dest_cap = amxc_htable_capacity(dest);
375 
376  retval = 0;
377  if(dest_cap < needed_cap) {
378  retval = amxc_htable_grow(dest, needed_cap - dest_cap);
379  }
380  when_failed(retval, exit);
381 
382  amxc_htable_for_each(it, src) {
383  amxc_htable_insert_it(dest, it);
384  }
385 
386  retval = 0;
387 
388 exit:
389  return retval;
390 }
AMXC_INLINE size_t amxc_htable_capacity(const amxc_htable_t *const htable)
Calculates the capacity of the hash table.
Definition: amxc_htable.h:351

◆ amxc_htable_new()

int amxc_htable_new ( amxc_htable_t **  htable,
const size_t  reserve 
)

Allocates a hash table.

Allocates and initializes memory to store a hash table. This function allocates memory from the heap, if a hash table is on the stack, it can be initialized using function amxc_htable_init

Note
The allocated memory must be freed when not used anymore, use amxc_htable_delete to free the memory
Parameters
htablea pointer to the location where the pointer to the new hash table can be stored
reserveNumber of items that needs to be reserved
Returns
-1 if an error occurred. 0 on success

Definition at line 148 of file amxc_htable.c.

148  {
149  int retval = -1;
150  when_null(htable, exit);
151 
152  *htable = (amxc_htable_t*) calloc(1, sizeof(amxc_htable_t));
153  when_null(*htable, exit);
154 
155  retval = amxc_htable_init(*htable, reserve);
156  if(retval == -1) {
157  free(*htable);
158  *htable = NULL;
159  }
160 
161 exit:
162  return retval;
163 }
int amxc_htable_init(amxc_htable_t *const htable, const size_t reserve)
Initializes a hash table.
Definition: amxc_htable.c:185
The hash table structure.
Definition: amxc_htable.h:175

◆ amxc_htable_set_hash_func()

void amxc_htable_set_hash_func ( amxc_htable_t *const  htable,
amxc_htable_hash_func_t  func 
)

Sets the hash function for the hash table.

A custom implementation for hash calculation function can be set on the hash table. By default the amxc_BKDR_hash function is set to calculate the hashes. Other hash functions are available, see Hash functions

Parameters
htablea pointer to the htable structure
funcpointer to a function that is called for each hash that needs be calculated

Definition at line 211 of file amxc_htable.c.

212  {
213  when_null(htable, exit);
214 
215  if(func != NULL) {
216  htable->hfunc = func;
217  } else {
219  }
220 
221 exit:
222  return;
223 }

◆ amxc_htable_size()

AMXC_INLINE size_t amxc_htable_size ( const amxc_htable_t *const  htable)

Calculates the size of the hash table.

The size of the hash table is expressed in items.

Note
Use amxc_htable_is_empty to check if a hash table is empty, do not use this function to check if the hash table is empty. This function will iterate over all pre-allocated buckets, and could have a performance impact for large hash tables.
Parameters
htablea pointer to the hash table structure
Returns
returns the number of items in hash table

Definition at line 334 of file amxc_htable.h.

334  {
335  return htable != NULL ? htable->items : 0;
336 }

◆ amxc_htable_take()

amxc_htable_it_t* amxc_htable_take ( amxc_htable_t *const  htable,
const char *const  key 
)

Removes a hash table iterator from the hash table.

The key provided is converted into an index using amxc_htable_key2index. If multiple items are available at the calculated position with the same key, (collision) the first one is removed and returned.

Note
The item is removed from the hash table. To fetch the next item in the hash table with the same key, call this function again.
Use amxc_htable_it_clean to clean up the iterator.
Parameters
htablea pointer to the hash table structure
keythe item key
Returns
Pointer to the hash table iterator or NULL if no iterator was stored with the given key. The pointer can be converted to the real data pointer using amxc_htable_it_get_data

Definition at line 304 of file amxc_htable.c.

305  {
307  if(it != NULL) {
309  }
310  return it;
311 }

◆ amxc_htable_take_first()

AMXC_INLINE amxc_htable_it_t* amxc_htable_take_first ( const amxc_htable_t *const  htable)

Removes the first item stored in the table.

This function iterates the table from the beginning and removes and returns the first one encounter.

Note
The order of the items in the table is not the same as the order they were inserted in the table. So the first item found can be different then the first item inserted.
Parameters
htablea pointer to the hash table structure
Returns
Pointer to the hash table iterator or NULL if no items were stored in the hash table.

Definition at line 696 of file amxc_htable.h.

696  {
699  return it;
700 }