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  assert(tbl->qmutex == NULL);
180  qhashtbl_free(tbl);
181  }
182  return NULL;
183 }
184 
185 /**
186  * qhashtbl->put(): Put an object into this table.
187  *
188  * @param tbl qhashtbl_t container pointer.
189  * @param name key name
190  * @param data data object
191  * @param size size of data object
192  *
193  * @return true if successful, otherwise returns false
194  * @retval errno will be set in error condition.
195  * - EINVAL : Invalid argument.
196  * - ENOMEM : Memory allocation failure.
197  */
198 bool qhashtbl_put(qhashtbl_t *tbl, const char *name, const void *data,
199  size_t size) {
200  if (name == NULL || data == NULL) {
201  errno = EINVAL;
202  return false;
203  }
204 
205  // get hash integer
206  uint32_t hash = qhashmurmur3_32(name, strlen(name));
207  int idx = hash % tbl->range;
208 
209  qhashtbl_lock(tbl);
210 
211  // find existence key
212  qhashtbl_obj_t *obj;
213  for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
214  if (obj->hash == hash && !strcmp(obj->name, name)) {
215  break;
216  }
217  }
218 
219  // duplicate object
220  char *dupname = strdup(name);
221  void *dupdata = malloc(size);
222  if (dupname == NULL || dupdata == NULL) {
223  free(dupname);
224  free(dupdata);
225  qhashtbl_unlock(tbl);
226  errno = ENOMEM;
227  return false;
228  }
229  memcpy(dupdata, data, size);
230 
231  // put into table
232  if (obj == NULL) {
233  // insert
234  obj = (qhashtbl_obj_t *) calloc(1, sizeof(qhashtbl_obj_t));
235  if (obj == NULL) {
236  free(dupname);
237  free(dupdata);
238  qhashtbl_unlock(tbl);
239  errno = ENOMEM;
240  return false;
241  }
242 
243  if (tbl->slots[idx] != NULL) {
244  // insert at the beginning
245  obj->next = tbl->slots[idx];
246  }
247  tbl->slots[idx] = obj;
248 
249  // increase counter
250  tbl->num++;
251  } else {
252  // replace
253  free(obj->name);
254  free(obj->data);
255  }
256 
257  // set data
258  obj->hash = hash;
259  obj->name = dupname;
260  obj->data = dupdata;
261  obj->size = size;
262 
263  qhashtbl_unlock(tbl);
264  return true;
265 }
266 
267 /**
268  * qhashtbl->putstr(): Put a string into this table.
269  *
270  * @param tbl qhashtbl_t container pointer.
271  * @param name key name.
272  * @param str string data.
273  *
274  * @return true if successful, otherwise returns false.
275  * @retval errno will be set in error condition.
276  * - EINVAL : Invalid argument.
277  * - ENOMEM : Memory allocation failure.
278  */
279 bool qhashtbl_putstr(qhashtbl_t *tbl, const char *name, const char *str) {
280  return qhashtbl_put(tbl, name, str, (str != NULL) ? (strlen(str) + 1) : 0);
281 }
282 
283 /**
284  * qhashtbl->putstrf(): Put a formatted string into this table.
285  *
286  * @param tbl qhashtbl_t container pointer.
287  * @param name key name.
288  * @param format formatted string data.
289  *
290  * @return true if successful, otherwise returns false.
291  * @retval errno will be set in error condition.
292  * - EINVAL : Invalid argument.
293  * - ENOMEM : Memory allocation failure.
294  */
295 bool qhashtbl_putstrf(qhashtbl_t *tbl, const char *name, const char *format, ...) {
296  char *str;
297  DYNAMIC_VSPRINTF(str, format);
298  if (str == NULL) {
299  errno = ENOMEM;
300  return false;
301  }
302 
303  bool ret = qhashtbl_putstr(tbl, name, str);
304  free(str);
305  return ret;
306 }
307 
308 /**
309  * qhashtbl->putint(): Put a integer into this table as string type.
310  *
311  * @param tbl qhashtbl_t container pointer.
312  * @param name key name.
313  * @param num integer data.
314  *
315  * @return true if successful, otherwise returns false.
316  * @retval errno will be set in error condition.
317  * - EINVAL : Invalid argument.
318  * - ENOMEM : Memory allocation failure.
319  *
320  * @note
321  * The integer will be converted to a string object and stored as string object.
322  */
323 bool qhashtbl_putint(qhashtbl_t *tbl, const char *name, const int64_t num) {
324  char str[20 + 1];
325  snprintf(str, sizeof(str), "%"PRId64, num);
326  return qhashtbl_putstr(tbl, name, str);
327 }
328 
329 /**
330  * qhashtbl->get(): Get an object from this table.
331  *
332  * @param tbl qhashtbl_t container pointer.
333  * @param name key name.
334  * @param size if not NULL, oject size will be stored.
335  * @param newmem whether or not to allocate memory for the data.
336  *
337  * @return a pointer of data if the key is found, otherwise returns NULL.
338  * @retval errno will be set in error condition.
339  * - ENOENT : No such key found.
340  * - EINVAL : Invalid argument.
341  * - ENOMEM : Memory allocation failure.
342  *
343  * @code
344  * qhashtbl_t *tbl = qhashtbl(0, 0);
345  * (...codes...)
346  *
347  * // with newmem flag unset
348  * size_t size;
349  * void *data = (struct myobj*)tbl->get(tbl, "key_name", &size, false);
350  *
351  * // with newmem flag set
352  * size_t size;
353  * void *data = (struct myobj*)tbl->get(tbl, "key_name", &size, true);
354  * free(data);
355  * @endcode
356  *
357  * @note
358  * If newmem flag is set, returned data will be malloced and should be
359  * deallocated by user. Otherwise returned pointer will point internal buffer
360  * directly and should not be de-allocated by user. In thread-safe mode,
361  * newmem flag must be set to true always.
362  */
363 void *qhashtbl_get(qhashtbl_t *tbl, const char *name, size_t *size, bool newmem) {
364  if (name == NULL) {
365  errno = EINVAL;
366  return NULL;
367  }
368 
369  uint32_t hash = qhashmurmur3_32(name, strlen(name));
370  int idx = hash % tbl->range;
371 
372  qhashtbl_lock(tbl);
373 
374  // find key
375  qhashtbl_obj_t *obj;
376  for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
377  if (obj->hash == hash && !strcmp(obj->name, name)) {
378  break;
379  }
380  }
381 
382  void *data = NULL;
383  if (obj != NULL) {
384  if (newmem == false) {
385  data = obj->data;
386  } else {
387  data = malloc(obj->size);
388  if (data == NULL) {
389  errno = ENOMEM;
390  return NULL;
391  }
392  memcpy(data, obj->data, obj->size);
393  }
394  if (size != NULL && data != NULL)
395  *size = obj->size;
396  }
397 
398  qhashtbl_unlock(tbl);
399 
400  if (data == NULL)
401  errno = ENOENT;
402  return data;
403 }
404 
405 /**
406  * qhashtbl->getstr(): Finds an object and returns as string type.
407  *
408  * @param tbl qhashtbl_t container pointer.
409  * @param name key name
410  * @param newmem whether or not to allocate memory for the data.
411  *
412  * @return a pointer of data if the key is found, otherwise returns NULL.
413  * @retval errno will be set in error condition.
414  * - ENOENT : No such key found.
415  * - EINVAL : Invalid argument.
416  * - ENOMEM : Memory allocation failure.
417  *
418  * @note
419  * If newmem flag is set, returned data will be malloced and should be
420  * deallocated by user.
421  */
422 char *qhashtbl_getstr(qhashtbl_t *tbl, const char *name, const bool newmem) {
423  return qhashtbl_get(tbl, name, NULL, newmem);
424 }
425 
426 /**
427  * qhashtbl->getint(): Finds an object with given name and returns as
428  * integer type.
429  *
430  * @param tbl qhashtbl_t container pointer.
431  * @param name key name
432  *
433  * @return value integer if successful, otherwise(not found) returns 0
434  * @retval errno will be set in error condition.
435  * - ENOENT : No such key found.
436  * - EINVAL : Invalid argument.
437  * - ENOMEM : Memory allocation failure.
438  */
439 int64_t qhashtbl_getint(qhashtbl_t *tbl, const char *name) {
440  int64_t num = 0;
441  char *str = qhashtbl_getstr(tbl, name, true);
442  if (str != NULL) {
443  num = atoll(str);
444  free(str);
445  }
446 
447  return num;
448 }
449 
450 /**
451  * qhashtbl->remove(): Remove an object from this table.
452  *
453  * @param tbl qhashtbl_t container pointer.
454  * @param name key name
455  *
456  * @return true if successful, otherwise(not found) returns false
457  * @retval errno will be set in error condition.
458  * - ENOENT : No such key found.
459  * - EINVAL : Invalid argument.
460  */
461 bool qhashtbl_remove(qhashtbl_t *tbl, const char *name) {
462  if (name == NULL) {
463  errno = EINVAL;
464  return false;
465  }
466 
467  qhashtbl_lock(tbl);
468 
469  uint32_t hash = qhashmurmur3_32(name, strlen(name));
470  int idx = hash % tbl->range;
471 
472  // find key
473  bool found = false;
474  qhashtbl_obj_t *prev = NULL;
475  qhashtbl_obj_t *obj;
476  for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
477  if (obj->hash == hash && !strcmp(obj->name, name)) {
478  // adjust link
479  if (prev == NULL)
480  tbl->slots[idx] = obj->next;
481  else
482  prev->next = obj->next;
483 
484  // remove
485  free(obj->name);
486  free(obj->data);
487  free(obj);
488 
489  found = true;
490  tbl->num--;
491  break;
492  }
493 
494  prev = obj;
495  }
496 
497  qhashtbl_unlock(tbl);
498 
499  if (found == false)
500  errno = ENOENT;
501 
502  return found;
503 }
504 
505 /**
506  * qhashtbl->getnext(): Get next element.
507  *
508  * @param tbl qhashtbl_t container pointer.
509  * @param obj found data will be stored in this object
510  * @param newmem whether or not to allocate memory for the data.
511  *
512  * @return true if found otherwise returns false
513  * @retval errno will be set in error condition.
514  * - ENOENT : No next element.
515  * - EINVAL : Invalid argument.
516  * - ENOMEM : Memory allocation failure.
517  *
518  * @code
519  * qhashtbl_t *tbl = qhashtbl(0, 0);
520  * (...add data into list...)
521  *
522  * qhashtbl_obj_t obj;
523  * memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
524  * tbl->lock(tbl); // lock it when thread condition is expected
525  * while(tbl->getnext(tbl, &obj, false) == true) { // newmem is false
526  * printf("NAME=%s, DATA=%s, SIZE=%zu\n",
527  * obj.name, (char*)obj.data, obj.size);
528  * // do free obj.name and obj.data if newmem was set to true;
529  * }
530  * tbl->unlock(tbl);
531  * @endcode
532  *
533  * @note
534  * locking must be provided on user code when all element scan must be
535  * guaranteed where multiple threads concurrently update the table.
536  * It's ok not to lock the table on the user code even in thread condition,
537  * when concurreny is importand and all element scan in a path doesn't need
538  * to be guaranteed. In this case, new data inserted during the traversal
539  * will be show up in this scan or next scan. Make sure newmem flag is set
540  * if deletion is expected during the scan.
541  * Object obj should be initialized with 0 by using memset() before first call.
542  */
543 bool qhashtbl_getnext(qhashtbl_t *tbl, qhashtbl_obj_t *obj, const bool newmem) {
544  if (obj == NULL) {
545  errno = EINVAL;
546  return NULL;
547  }
548 
549  qhashtbl_lock(tbl);
550 
551  bool found = false;
552 
553  qhashtbl_obj_t *cursor = NULL;
554  int idx = 0;
555  if (obj->name != NULL) {
556  idx = (obj->hash % tbl->range) + 1;
557  cursor = obj->next;
558  }
559 
560  if (cursor != NULL) {
561  // has link
562  found = true;
563  } else {
564  // search from next index
565  for (; idx < tbl->range; idx++) {
566  if (tbl->slots[idx] != NULL) {
567  cursor = tbl->slots[idx];
568  found = true;
569  break;
570  }
571  }
572  }
573 
574  if (cursor != NULL) {
575  if (newmem == true) {
576  obj->name = strdup(cursor->name);
577  obj->data = malloc(cursor->size);
578  if (obj->name == NULL || obj->data == NULL) {
579  DEBUG("getnext(): Unable to allocate memory.");
580  free(obj->name);
581  free(obj->data);
582  qhashtbl_unlock(tbl);
583  errno = ENOMEM;
584  return false;
585  }
586  memcpy(obj->data, cursor->data, cursor->size);
587  obj->size = cursor->size;
588  } else {
589  obj->name = cursor->name;
590  obj->data = cursor->data;
591  }
592  obj->hash = cursor->hash;
593  obj->size = cursor->size;
594  obj->next = cursor->next;
595 
596  }
597 
598  qhashtbl_unlock(tbl);
599 
600  if (found == false)
601  errno = ENOENT;
602 
603  return found;
604 }
605 
606 /**
607  * qhashtbl->size(): Returns the number of keys in this hashtable.
608  *
609  * @param tbl qhashtbl_t container pointer.
610  *
611  * @return number of elements stored
612  */
613 size_t qhashtbl_size(qhashtbl_t *tbl) {
614  return tbl->num;
615 }
616 
617 /**
618  * qhashtbl->clear(): Clears this hashtable so that it contains no keys.
619  *
620  * @param tbl qhashtbl_t container pointer.
621  */
622 void qhashtbl_clear(qhashtbl_t *tbl) {
623  qhashtbl_lock(tbl);
624  int idx;
625  for (idx = 0; idx < tbl->range && tbl->num > 0; idx++) {
626  if (tbl->slots[idx] == NULL)
627  continue;
628  qhashtbl_obj_t *obj = tbl->slots[idx];
629  tbl->slots[idx] = NULL;
630  while (obj != NULL) {
631  qhashtbl_obj_t *next = obj->next;
632  free(obj->name);
633  free(obj->data);
634  free(obj);
635  obj = next;
636 
637  tbl->num--;
638  }
639  }
640 
641  qhashtbl_unlock(tbl);
642 }
643 
644 /**
645  * qhashtbl->debug(): Print hash table for debugging purpose
646  *
647  * @param tbl qhashtbl_t container pointer.
648  * @param out output stream
649  *
650  * @return true if successful, otherwise returns false.
651  * @retval errno will be set in error condition.
652  * - EIO : Invalid output stream.
653  */
654 bool qhashtbl_debug(qhashtbl_t *tbl, FILE *out) {
655  if (out == NULL) {
656  errno = EIO;
657  return false;
658  }
659 
660  qhashtbl_obj_t obj;
661  memset((void *) &obj, 0, sizeof(obj)); // must be cleared before call
662  qhashtbl_lock(tbl);
663  while (tbl->getnext(tbl, &obj, false) == true) {
664  fprintf(out, "%s=", obj.name);
665  _q_textout(out, obj.data, obj.size, MAX_HUMANOUT);
666  fprintf(out, " (%zu, %08x)\n", obj.size, obj.hash);
667  }
668  qhashtbl_unlock(tbl);
669 
670  return true;
671 }
672 
673 /**
674  * qhashtbl->lock(): Enter critical section.
675  *
676  * @param tbl qhashtbl_t container pointer.
677  *
678  * @note
679  * From user side, normally locking operation is only needed when traverse
680  * all elements using qhashtbl->getnext().
681  *
682  * @note
683  * This operation will do nothing if QHASHTBL_THREADSAFE option was not
684  * given at the initialization time.
685  */
686 void qhashtbl_lock(qhashtbl_t *tbl) {
687  Q_MUTEX_ENTER(tbl->qmutex);
688 }
689 
690 /**
691  * qhashtbl->unlock(): Leave critical section.
692  *
693  * @param tbl qhashtbl_t container pointer.
694  *
695  * @note
696  * This operation will do nothing if QHASHTBL_THREADSAFE option was not
697  * given at the initialization time.
698  */
699 void qhashtbl_unlock(qhashtbl_t *tbl) {
700  Q_MUTEX_LEAVE(tbl->qmutex);
701 }
702 
703 /**
704  * qhashtbl->free(): De-allocate hash table
705  *
706  * @param tbl qhashtbl_t container pointer.
707  */
708 void qhashtbl_free(qhashtbl_t *tbl) {
709  qhashtbl_lock(tbl);
710  qhashtbl_clear(tbl);
711  free(tbl->slots);
712  qhashtbl_unlock(tbl);
713  Q_MUTEX_DESTROY(tbl->qmutex);
714  free(tbl);
715 }
bool qhashtbl_remove(qhashtbl_t *tbl, const char *name)
qhashtbl->remove(): Remove an object from this table.
Definition: qhashtbl.c:461
size_t qhashtbl_size(qhashtbl_t *tbl)
qhashtbl->size(): Returns the number of keys in this hashtable.
Definition: qhashtbl.c:613
void qhashtbl_free(qhashtbl_t *tbl)
qhashtbl->free(): De-allocate hash table
Definition: qhashtbl.c:708
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:323
void qhashtbl_clear(qhashtbl_t *tbl)
qhashtbl->clear(): Clears this hashtable so that it contains no keys.
Definition: qhashtbl.c:622
bool qhashtbl_putstr(qhashtbl_t *tbl, const char *name, const char *str)
qhashtbl->putstr(): Put a string into this table.
Definition: qhashtbl.c:279
void qhashtbl_lock(qhashtbl_t *tbl)
qhashtbl->lock(): Enter critical section.
Definition: qhashtbl.c:686
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:439
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:198
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:422
#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:699
bool qhashtbl_getnext(qhashtbl_t *tbl, qhashtbl_obj_t *obj, const bool newmem)
qhashtbl->getnext(): Get next element.
Definition: qhashtbl.c:543
bool qhashtbl_putstrf(qhashtbl_t *tbl, const char *name, const char *format,...)
qhashtbl->putstrf(): Put a formatted string into this table.
Definition: qhashtbl.c:295
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:363
bool qhashtbl_debug(qhashtbl_t *tbl, FILE *out)
qhashtbl->debug(): Print hash table for debugging purpose
Definition: qhashtbl.c:654