qLibc
qhashtbl.c
Go to the documentation of this file.
1 /******************************************************************************
2  * qLibc
3  *
4  * Copyright (c) 2010-2015 Seungyoung Kim.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *****************************************************************************/
28 
29 /**
30  * @file qhashtbl.c Hash-table container implementation.
31  *
32  * qhashtbl implements a hash table, which maps keys to values. Key is a unique
33  * string and value is any non-null object. The creator qhashtbl() has a
34  * parameter that affect its performance: initial hash range. The hash range
35  * is the number of slots(pointers) in the hash table. in the case of a hash
36  * collision, a single slots stores multiple elements using linked-list
37  * structure, which must be searched sequentially. So lower range than the
38  * number of elements decreases the space overhead but increases the number of
39  * hash collisions and consequently it increases the time cost to look up an
40  * element.
41  *
42  * @code
43  * [Internal Structure Example for 10-slot hash table]
44  *
45  * RANGE NAMED-OBJECT-LIST
46  * ===== =================
47  * [ 0 ] -> [hash=320,key3=value] -> [hash=210,key5=value] -> [hash=110,...]
48  * [ 1 ] -> [hash=1,key1=value]
49  * [ 2 ]
50  * [ 3 ] -> [hash=873,key4=value]
51  * [ 4 ] -> [hash=2674,key11=value] -> [hash=214,key5=value]
52  * [ 5 ] -> [hash=8545,key10=value]
53  * [ 6 ] -> [hash=9226,key9=value]
54  * [ 7 ]
55  * [ 8 ] -> [hash=8,key6=value] -> [hash=88,key8=value]
56  * [ 9 ] -> [hash=12439,key7=value]
57  * @endcode
58  *
59  * @code
60  * // create a hash-table with 10 hash-index range.
61  * // Please be aware, the hash-index range 10 does not mean the number of
62  * // objects which can be stored. You can put as many as you want but if
63  * // this range is too small, hash conflict will happen and fetch time will
64  * // slightly increase.
65  * qhashtbl_t *tbl = qhashtbl(0, QHASHTBL_THREADSAFE);
66  *
67  * // put objects into table.
68  * tbl->put(tbl, "sample1", "binary", 6);
69  * tbl->putstr(tbl, "sample2", "string");
70  * tbl->putint(tbl, "sample3", 1);
71  *
72  * // debug print out
73  * tbl->debug(tbl, stdout, true);
74  *
75  * // get objects
76  * void *sample1 = tbl->get(tbl, "sample1", &size, true);
77  * char *sample2 = tbl->getstr(tbl, "sample2", false);
78  * int sample3 = tbl->getint(tbl, "sample3");
79  *
80  * // sample1 is memalloced
81  * free(sample1);
82  *
83  * // release table
84  * tbl->free(tbl);
85  * @endcode
86  */
87 
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <stdbool.h>
91 #include <stdint.h>
92 #include <inttypes.h>
93 #include <stdarg.h>
94 #include <string.h>
95 #include <assert.h>
96 #include <errno.h>
97 #include "qinternal.h"
98 #include "utilities/qhash.h"
99 #include "containers/qhashtbl.h"
100 
101 #define DEFAULT_INDEX_RANGE (1000) /*!< default value of hash-index range */
102 
103 /**
104  * Initialize hash table.
105  *
106  * @param range initial size of index range. Value of 0 will use default value, DEFAULT_INDEX_RANGE;
107  * @param options combination of initialization options.
108  *
109  * @return a pointer of malloced qhashtbl_t, otherwise returns NULL.
110  * @retval errno will be set in error condition.
111  * - ENOMEM : Memory allocation failure.
112  *
113  * @code
114  * // create a hash-table.
115  * qhashtbl_t *basic_hashtbl = qhashtbl(0, 0);
116  *
117  * // create a large hash-table for millions of keys with thread-safe option.
118  * qhashtbl_t *small_hashtbl = qhashtbl(1000000, QHASHTBL_THREADSAFE);
119  * @endcode
120  *
121  * @note
122  * Setting the right range is a magic.
123  * In practice, pick a value between (total keys / 3) ~ (total keys * 2).
124  * Available options:
125  * - QHASHTBL_THREADSAFE - make it thread-safe.
126  */
127 qhashtbl_t *qhashtbl(size_t range, int options) {
128  if (range == 0) {
129  range = DEFAULT_INDEX_RANGE;
130  }
131 
132  qhashtbl_t *tbl = (qhashtbl_t *) calloc(1, sizeof(qhashtbl_t));
133  if (tbl == NULL)
134  goto malloc_failure;
135 
136  // allocate table space
137  tbl->slots = (qhashtbl_obj_t **) calloc(range, sizeof(qhashtbl_obj_t *));
138  if (tbl->slots == NULL)
139  goto malloc_failure;
140 
141  // handle options.
142  if (options & QHASHTBL_THREADSAFE) {
143  Q_MUTEX_NEW(tbl->qmutex, true);
144  if (tbl->qmutex == NULL)
145  goto malloc_failure;
146  }
147 
148  // assign methods
149  tbl->put = qhashtbl_put;
150  tbl->putstr = qhashtbl_putstr;
151  tbl->putstrf = qhashtbl_putstrf;
152  tbl->putint = qhashtbl_putint;
153 
154  tbl->get = qhashtbl_get;
155  tbl->getstr = qhashtbl_getstr;
156  tbl->getint = qhashtbl_getint;
157 
158  tbl->remove = qhashtbl_remove;
159 
160  tbl->getnext = qhashtbl_getnext;
161 
162  tbl->size = qhashtbl_size;
163  tbl->clear = qhashtbl_clear;
164  tbl->debug = qhashtbl_debug;
165 
166  tbl->lock = qhashtbl_lock;
167  tbl->unlock = qhashtbl_unlock;
168 
169  tbl->free = qhashtbl_free;
170 
171  // set table range.
172  tbl->range = range;
173 
174  return tbl;
175 
176  malloc_failure:
177  errno = ENOMEM;
178  if (tbl) {
179  free(tbl->slots);
180  assert(tbl->qmutex == NULL);
181  qhashtbl_free(tbl);
182  }
183  return NULL;
184 }
185 
186 /**
187  * qhashtbl->put(): Put an object into this table.
188  *
189  * @param tbl qhashtbl_t container pointer.
190  * @param name key name
191  * @param data data object
192  * @param size size of data object
193  *
194  * @return true if successful, otherwise returns false
195  * @retval errno will be set in error condition.
196  * - EINVAL : Invalid argument.
197  * - ENOMEM : Memory allocation failure.
198  */
199 bool qhashtbl_put(qhashtbl_t *tbl, const char *name, const void *data,
200  size_t size) {
201  if (name == NULL || data == NULL) {
202  errno = EINVAL;
203  return false;
204  }
205 
206  // get hash integer
207  uint32_t hash = qhashmurmur3_32(name, strlen(name));
208  int idx = hash % tbl->range;
209 
210  qhashtbl_lock(tbl);
211 
212  // find existence key
213  qhashtbl_obj_t *obj;
214  for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
215  if (obj->hash == hash && !strcmp(obj->name, name)) {
216  break;
217  }
218  }
219 
220  // duplicate object
221  char *dupname = strdup(name);
222  void *dupdata = malloc(size);
223  if (dupname == NULL || dupdata == NULL) {
224  free(dupname);
225  free(dupdata);
226  qhashtbl_unlock(tbl);
227  errno = ENOMEM;
228  return false;
229  }
230  memcpy(dupdata, data, size);
231 
232  // put into table
233  if (obj == NULL) {
234  // insert
235  obj = (qhashtbl_obj_t *) calloc(1, sizeof(qhashtbl_obj_t));
236  if (obj == NULL) {
237  free(dupname);
238  free(dupdata);
239  qhashtbl_unlock(tbl);
240  errno = ENOMEM;
241  return false;
242  }
243 
244  if (tbl->slots[idx] != NULL) {
245  // insert at the beginning
246  obj->next = tbl->slots[idx];
247  }
248  tbl->slots[idx] = obj;
249 
250  // increase counter
251  tbl->num++;
252  } else {
253  // replace
254  free(obj->name);
255  free(obj->data);
256  }
257 
258  // set data
259  obj->hash = hash;
260  obj->name = dupname;
261  obj->data = dupdata;
262  obj->size = size;
263 
264  qhashtbl_unlock(tbl);
265  return true;
266 }
267 
268 /**
269  * qhashtbl->putstr(): Put a string into this table.
270  *
271  * @param tbl qhashtbl_t container pointer.
272  * @param name key name.
273  * @param str string data.
274  *
275  * @return true if successful, otherwise returns false.
276  * @retval errno will be set in error condition.
277  * - EINVAL : Invalid argument.
278  * - ENOMEM : Memory allocation failure.
279  */
280 bool qhashtbl_putstr(qhashtbl_t *tbl, const char *name, const char *str) {
281  return qhashtbl_put(tbl, name, str, (str != NULL) ? (strlen(str) + 1) : 0);
282 }
283 
284 /**
285  * qhashtbl->putstrf(): Put a formatted string into this table.
286  *
287  * @param tbl qhashtbl_t container pointer.
288  * @param name key name.
289  * @param format formatted string data.
290  *
291  * @return true if successful, otherwise returns false.
292  * @retval errno will be set in error condition.
293  * - EINVAL : Invalid argument.
294  * - ENOMEM : Memory allocation failure.
295  */
296 bool qhashtbl_putstrf(qhashtbl_t *tbl, const char *name, const char *format, ...) {
297  char *str;
298  DYNAMIC_VSPRINTF(str, format);
299  if (str == NULL) {
300  errno = ENOMEM;
301  return false;
302  }
303 
304  bool ret = qhashtbl_putstr(tbl, name, str);
305  free(str);
306  return ret;
307 }
308 
309 /**
310  * qhashtbl->putint(): Put a integer into this table as string type.
311  *
312  * @param tbl qhashtbl_t container pointer.
313  * @param name key name.
314  * @param num integer data.
315  *
316  * @return true if successful, otherwise returns false.
317  * @retval errno will be set in error condition.
318  * - EINVAL : Invalid argument.
319  * - ENOMEM : Memory allocation failure.
320  *
321  * @note
322  * The integer will be converted to a string object and stored as string object.
323  */
324 bool qhashtbl_putint(qhashtbl_t *tbl, const char *name, const int64_t num) {
325  char str[20 + 1];
326  snprintf(str, sizeof(str), "%"PRId64, num);
327  return qhashtbl_putstr(tbl, name, str);
328 }
329 
330 /**
331  * qhashtbl->get(): Get an object from this table.
332  *
333  * @param tbl qhashtbl_t container pointer.
334  * @param name key name.
335  * @param size if not NULL, oject size will be stored.
336  * @param newmem whether or not to allocate memory for the data.
337  *
338  * @return a pointer of data if the key is found, otherwise returns NULL.
339  * @retval errno will be set in error condition.
340  * - ENOENT : No such key found.
341  * - EINVAL : Invalid argument.
342  * - ENOMEM : Memory allocation failure.
343  *
344  * @code
345  * qhashtbl_t *tbl = qhashtbl(0, 0);
346  * (...codes...)
347  *
348  * // with newmem flag unset
349  * size_t size;
350  * void *data = (struct myobj*)tbl->get(tbl, "key_name", &size, false);
351  *
352  * // with newmem flag set
353  * size_t size;
354  * void *data = (struct myobj*)tbl->get(tbl, "key_name", &size, true);
355  * free(data);
356  * @endcode
357  *
358  * @note
359  * If newmem flag is set, returned data will be malloced and should be
360  * deallocated by user. Otherwise returned pointer will point internal buffer
361  * directly and should not be de-allocated by user. In thread-safe mode,
362  * newmem flag must be set to true always.
363  */
364 void *qhashtbl_get(qhashtbl_t *tbl, const char *name, size_t *size, bool newmem) {
365  if (name == NULL) {
366  errno = EINVAL;
367  return NULL;
368  }
369 
370  uint32_t hash = qhashmurmur3_32(name, strlen(name));
371  int idx = hash % tbl->range;
372 
373  qhashtbl_lock(tbl);
374 
375  // find key
376  qhashtbl_obj_t *obj;
377  for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
378  if (obj->hash == hash && !strcmp(obj->name, name)) {
379  break;
380  }
381  }
382 
383  void *data = NULL;
384  if (obj != NULL) {
385  if (newmem == false) {
386  data = obj->data;
387  } else {
388  data = malloc(obj->size);
389  if (data == NULL) {
390  errno = ENOMEM;
391  return NULL;
392  }
393  memcpy(data, obj->data, obj->size);
394  }
395  if (size != NULL && data != NULL)
396  *size = obj->size;
397  }
398 
399  qhashtbl_unlock(tbl);
400 
401  if (data == NULL)
402  errno = ENOENT;
403  return data;
404 }
405 
406 /**
407  * qhashtbl->getstr(): Finds an object and returns as string type.
408  *
409  * @param tbl qhashtbl_t container pointer.
410  * @param name key name
411  * @param newmem whether or not to allocate memory for the data.
412  *
413  * @return a pointer of data if the key is found, otherwise returns NULL.
414  * @retval errno will be set in error condition.
415  * - ENOENT : No such key found.
416  * - EINVAL : Invalid argument.
417  * - ENOMEM : Memory allocation failure.
418  *
419  * @note
420  * If newmem flag is set, returned data will be malloced and should be
421  * deallocated by user.
422  */
423 char *qhashtbl_getstr(qhashtbl_t *tbl, const char *name, const bool newmem) {
424  return qhashtbl_get(tbl, name, NULL, newmem);
425 }
426 
427 /**
428  * qhashtbl->getint(): Finds an object with given name and returns as
429  * integer type.
430  *
431  * @param tbl qhashtbl_t container pointer.
432  * @param name key name
433  *
434  * @return value integer if successful, otherwise(not found) returns 0
435  * @retval errno will be set in error condition.
436  * - ENOENT : No such key found.
437  * - EINVAL : Invalid argument.
438  * - ENOMEM : Memory allocation failure.
439  */
440 int64_t qhashtbl_getint(qhashtbl_t *tbl, const char *name) {
441  int64_t num = 0;
442  char *str = qhashtbl_getstr(tbl, name, true);
443  if (str != NULL) {
444  num = atoll(str);
445  free(str);
446  }
447 
448  return num;
449 }
450 
451 /**
452  * qhashtbl->remove(): Remove an object from this table.
453  *
454  * @param tbl qhashtbl_t container pointer.
455  * @param name key name
456  *
457  * @return true if successful, otherwise(not found) returns false
458  * @retval errno will be set in error condition.
459  * - ENOENT : No such key found.
460  * - EINVAL : Invalid argument.
461  */
462 bool qhashtbl_remove(qhashtbl_t *tbl, const char *name) {
463  if (name == NULL) {
464  errno = EINVAL;
465  return false;
466  }
467 
468  qhashtbl_lock(tbl);
469 
470  uint32_t hash = qhashmurmur3_32(name, strlen(name));
471  int idx = hash % tbl->range;
472 
473  // find key
474  bool found = false;
475  qhashtbl_obj_t *prev = NULL;
476  qhashtbl_obj_t *obj;
477  for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
478  if (obj->hash == hash && !strcmp(obj->name, name)) {
479  // adjust link
480  if (prev == NULL)
481  tbl->slots[idx] = obj->next;
482  else
483  prev->next = obj->next;
484 
485  // remove
486  free(obj->name);
487  free(obj->data);
488  free(obj);
489 
490  found = true;
491  tbl->num--;
492  break;
493  }
494 
495  prev = obj;
496  }
497 
498  qhashtbl_unlock(tbl);
499 
500  if (found == false)
501  errno = ENOENT;
502 
503  return found;
504 }
505 
506 /**
507  * qhashtbl->getnext(): Get next element.
508  *
509  * @param tbl qhashtbl_t container pointer.
510  * @param obj found data will be stored in this object
511  * @param newmem whether or not to allocate memory for the data.
512  *
513  * @return true if found otherwise returns false
514  * @retval errno will be set in error condition.
515  * - ENOENT : No next element.
516  * - EINVAL : Invalid argument.
517  * - ENOMEM : Memory allocation failure.
518  *
519  * @code
520  * qhashtbl_t *tbl = qhashtbl(0, 0);
521  * (...add data into list...)
522  *
523  * qhashtbl_obj_t obj;
524  * memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
525  * tbl->lock(tbl); // lock it when thread condition is expected
526  * while(tbl->getnext(tbl, &obj, false) == true) { // newmem is false
527  * printf("NAME=%s, DATA=%s, SIZE=%zu\n",
528  * obj.name, (char*)obj.data, obj.size);
529  * // do free obj.name and obj.data if newmem was set to true;
530  * }
531  * tbl->unlock(tbl);
532  * @endcode
533  *
534  * @note
535  * locking must be provided on user code when all element scan must be
536  * guaranteed where multiple threads concurrently update the table.
537  * It's ok not to lock the table on the user code even in thread condition,
538  * when concurreny is importand and all element scan in a path doesn't need
539  * to be guaranteed. In this case, new data inserted during the traversal
540  * will be show up in this scan or next scan. Make sure newmem flag is set
541  * if deletion is expected during the scan.
542  * Object obj should be initialized with 0 by using memset() before first call.
543  */
544 bool qhashtbl_getnext(qhashtbl_t *tbl, qhashtbl_obj_t *obj, const bool newmem) {
545  if (obj == NULL) {
546  errno = EINVAL;
547  return NULL;
548  }
549 
550  qhashtbl_lock(tbl);
551 
552  bool found = false;
553 
554  qhashtbl_obj_t *cursor = NULL;
555  int idx = 0;
556  if (obj->name != NULL) {
557  idx = (obj->hash % tbl->range) + 1;
558  cursor = obj->next;
559  }
560 
561  if (cursor != NULL) {
562  // has link
563  found = true;
564  } else {
565  // search from next index
566  for (; idx < tbl->range; idx++) {
567  if (tbl->slots[idx] != NULL) {
568  cursor = tbl->slots[idx];
569  found = true;
570  break;
571  }
572  }
573  }
574 
575  if (cursor != NULL) {
576  if (newmem == true) {
577  obj->name = strdup(cursor->name);
578  obj->data = malloc(cursor->size);
579  if (obj->name == NULL || obj->data == NULL) {
580  DEBUG("getnext(): Unable to allocate memory.");
581  free(obj->name);
582  free(obj->data);
583  qhashtbl_unlock(tbl);
584  errno = ENOMEM;
585  return false;
586  }
587  memcpy(obj->data, cursor->data, cursor->size);
588  obj->size = cursor->size;
589  } else {
590  obj->name = cursor->name;
591  obj->data = cursor->data;
592  }
593  obj->hash = cursor->hash;
594  obj->size = cursor->size;
595  obj->next = cursor->next;
596 
597  }
598 
599  qhashtbl_unlock(tbl);
600 
601  if (found == false)
602  errno = ENOENT;
603 
604  return found;
605 }
606 
607 /**
608  * qhashtbl->size(): Returns the number of keys in this hashtable.
609  *
610  * @param tbl qhashtbl_t container pointer.
611  *
612  * @return number of elements stored
613  */
614 size_t qhashtbl_size(qhashtbl_t *tbl) {
615  return tbl->num;
616 }
617 
618 /**
619  * qhashtbl->clear(): Clears this hashtable so that it contains no keys.
620  *
621  * @param tbl qhashtbl_t container pointer.
622  */
623 void qhashtbl_clear(qhashtbl_t *tbl) {
624  qhashtbl_lock(tbl);
625  int idx;
626  for (idx = 0; idx < tbl->range && tbl->num > 0; idx++) {
627  if (tbl->slots[idx] == NULL)
628  continue;
629  qhashtbl_obj_t *obj = tbl->slots[idx];
630  tbl->slots[idx] = NULL;
631  while (obj != NULL) {
632  qhashtbl_obj_t *next = obj->next;
633  free(obj->name);
634  free(obj->data);
635  free(obj);
636  obj = next;
637 
638  tbl->num--;
639  }
640  }
641 
642  qhashtbl_unlock(tbl);
643 }
644 
645 /**
646  * qhashtbl->debug(): Print hash table for debugging purpose
647  *
648  * @param tbl qhashtbl_t container pointer.
649  * @param out output stream
650  *
651  * @return true if successful, otherwise returns false.
652  * @retval errno will be set in error condition.
653  * - EIO : Invalid output stream.
654  */
655 bool qhashtbl_debug(qhashtbl_t *tbl, FILE *out) {
656  if (out == NULL) {
657  errno = EIO;
658  return false;
659  }
660 
661  qhashtbl_obj_t obj;
662  memset((void *) &obj, 0, sizeof(obj)); // must be cleared before call
663  qhashtbl_lock(tbl);
664  while (tbl->getnext(tbl, &obj, false) == true) {
665  fprintf(out, "%s=", obj.name);
666  _q_textout(out, obj.data, obj.size, MAX_HUMANOUT);
667  fprintf(out, " (%zu, hash=%u)\n", obj.size, obj.hash);
668  }
669  qhashtbl_unlock(tbl);
670 
671  return true;
672 }
673 
674 /**
675  * qhashtbl->lock(): Enter critical section.
676  *
677  * @param tbl qhashtbl_t container pointer.
678  *
679  * @note
680  * From user side, normally locking operation is only needed when traverse
681  * all elements using qhashtbl->getnext().
682  *
683  * @note
684  * This operation will do nothing if QHASHTBL_THREADSAFE option was not
685  * given at the initialization time.
686  */
687 void qhashtbl_lock(qhashtbl_t *tbl) {
688  Q_MUTEX_ENTER(tbl->qmutex);
689 }
690 
691 /**
692  * qhashtbl->unlock(): Leave critical section.
693  *
694  * @param tbl qhashtbl_t container pointer.
695  *
696  * @note
697  * This operation will do nothing if QHASHTBL_THREADSAFE option was not
698  * given at the initialization time.
699  */
700 void qhashtbl_unlock(qhashtbl_t *tbl) {
701  Q_MUTEX_LEAVE(tbl->qmutex);
702 }
703 
704 /**
705  * qhashtbl->free(): De-allocate hash table
706  *
707  * @param tbl qhashtbl_t container pointer.
708  */
709 void qhashtbl_free(qhashtbl_t *tbl) {
710  qhashtbl_lock(tbl);
711  qhashtbl_clear(tbl);
712  free(tbl->slots);
713  qhashtbl_unlock(tbl);
714  Q_MUTEX_DESTROY(tbl->qmutex);
715  free(tbl);
716 }
bool qhashtbl_remove(qhashtbl_t *tbl, const char *name)
qhashtbl->remove(): Remove an object from this table.
Definition: qhashtbl.c:462
size_t qhashtbl_size(qhashtbl_t *tbl)
qhashtbl->size(): Returns the number of keys in this hashtable.
Definition: qhashtbl.c:614
void qhashtbl_free(qhashtbl_t *tbl)
qhashtbl->free(): De-allocate hash table
Definition: qhashtbl.c:709
bool qhashtbl_putint(qhashtbl_t *tbl, const char *name, const int64_t num)
qhashtbl->putint(): Put a integer into this table as string type.
Definition: qhashtbl.c:324
void qhashtbl_clear(qhashtbl_t *tbl)
qhashtbl->clear(): Clears this hashtable so that it contains no keys.
Definition: qhashtbl.c:623
bool qhashtbl_putstr(qhashtbl_t *tbl, const char *name, const char *str)
qhashtbl->putstr(): Put a string into this table.
Definition: qhashtbl.c:280
void qhashtbl_lock(qhashtbl_t *tbl)
qhashtbl->lock(): Enter critical section.
Definition: qhashtbl.c:687
int64_t qhashtbl_getint(qhashtbl_t *tbl, const char *name)
qhashtbl->getint(): Finds an object with given name and returns as integer type.
Definition: qhashtbl.c:440
bool qhashtbl_put(qhashtbl_t *tbl, const char *name, const void *data, size_t size)
qhashtbl->put(): Put an object into this table.
Definition: qhashtbl.c:199
char * qhashtbl_getstr(qhashtbl_t *tbl, const char *name, const bool newmem)
qhashtbl->getstr(): Finds an object and returns as string type.
Definition: qhashtbl.c:423
#define DEFAULT_INDEX_RANGE
Definition: qhashtbl.c:101
uint32_t qhashmurmur3_32(const void *data, size_t nbytes)
Get 32-bit Murmur3 hash.
Definition: qhash.c:258
qhashtbl_t * qhashtbl(size_t range, int options)
Initialize hash table.
Definition: qhashtbl.c:127
void qhashtbl_unlock(qhashtbl_t *tbl)
qhashtbl->unlock(): Leave critical section.
Definition: qhashtbl.c:700
bool qhashtbl_getnext(qhashtbl_t *tbl, qhashtbl_obj_t *obj, const bool newmem)
qhashtbl->getnext(): Get next element.
Definition: qhashtbl.c:544
bool qhashtbl_putstrf(qhashtbl_t *tbl, const char *name, const char *format,...)
qhashtbl->putstrf(): Put a formatted string into this table.
Definition: qhashtbl.c:296
void * qhashtbl_get(qhashtbl_t *tbl, const char *name, size_t *size, bool newmem)
qhashtbl->get(): Get an object from this table.
Definition: qhashtbl.c:364
bool qhashtbl_debug(qhashtbl_t *tbl, FILE *out)
qhashtbl->debug(): Print hash table for debugging purpose
Definition: qhashtbl.c:655