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 */
127qhashtbl_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 */
198bool 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 */
279bool 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 */
295bool 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 */
323bool 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 */
363void *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 */
422char *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 */
439int64_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 */
461bool 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 */
543bool 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 */
613size_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 */
622void 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 */
654bool 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 */
686void 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 */
699void 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 */
708void 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}
uint32_t qhashmurmur3_32(const void *data, size_t nbytes)
Get 32-bit Murmur3 hash.
Definition qhash.c:263
bool qhashtbl_remove(qhashtbl_t *tbl, const char *name)
qhashtbl->remove(): Remove an object from this table.
Definition qhashtbl.c:461
bool qhashtbl_debug(qhashtbl_t *tbl, FILE *out)
qhashtbl->debug(): Print hash table for debugging purpose
Definition qhashtbl.c:654
void qhashtbl_clear(qhashtbl_t *tbl)
qhashtbl->clear(): Clears this hashtable so that it contains no keys.
Definition qhashtbl.c:622
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
void qhashtbl_unlock(qhashtbl_t *tbl)
qhashtbl->unlock(): Leave critical section.
Definition qhashtbl.c:699
#define DEFAULT_INDEX_RANGE
Definition qhashtbl.c:101
void qhashtbl_free(qhashtbl_t *tbl)
qhashtbl->free(): De-allocate hash table
Definition qhashtbl.c:708
bool qhashtbl_getnext(qhashtbl_t *tbl, qhashtbl_obj_t *obj, const bool newmem)
qhashtbl->getnext(): Get next element.
Definition qhashtbl.c:543
size_t qhashtbl_size(qhashtbl_t *tbl)
qhashtbl->size(): Returns the number of keys in this hashtable.
Definition qhashtbl.c:613
qhashtbl_t * qhashtbl(size_t range, int options)
Initialize hash table.
Definition qhashtbl.c:127
void qhashtbl_lock(qhashtbl_t *tbl)
qhashtbl->lock(): Enter critical section.
Definition qhashtbl.c:686
bool qhashtbl_putstr(qhashtbl_t *tbl, const char *name, const char *str)
qhashtbl->putstr(): Put a string into this table.
Definition qhashtbl.c:279
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
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
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
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_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