209
static bool qhput(qhashtbl_t *tbl, char *key, int keylen, const void *data)
212
uint32_t hash = qhashmurmur3_32(key, keylen);
213
int idx = hash % tbl->range;
214
tbl->ncalls_put++; // debug
216
//log_error ("qhastbl:put: key=[%s], keylen=%d hash=%d, idx=%d, d=%x\n", key, keylen, hash, idx, data);
219
qhslot_t *slot = &tbl->slots[idx];
221
for (obj = slot->head; obj != NULL; obj = obj->next) {
222
if (obj->hash == hash && !strcmp(obj->key, key)) {
225
tbl->nwalks_put++; // debug: we walk one step in a chain of elements
231
obj = (qhnobj_t *)malloc(sizeof(qhnobj_t));
237
memset((void *)obj, 0, sizeof(qhnobj_t));
239
if (slot->tail != NULL) {
240
// connect old tail to this new tail
241
slot->tail->next = obj;
243
if (slot->head == NULL) {
244
// insert as very first element
256
obj->value = (void *)data;
259
/* Do not do anything.
260
* Keep the first definition in place, because consider this example
261
* if we would replace the object here:
263
* def A[NX] --> A's dimension is the first variable NX (a pointer to that)
264
* def NX --> hashtable stores this variable reference
266
* write NX --> value is stored in the NX variable found in the hash table
267
* write A --> dimension found (valid first pointer) but value is not found
268
* (stored in the second reference)
269
* At this point, A's dimension variable is first NX, but the value of
270
* write NX goes to the variable found here in the hash table.
203
278
static bool put(qhashtbl_t *tbl, const char *fullpath, const void *data)
208
283
int keylen = strlen(fullpath);
209
284
char *key = strdup (fullpath);
212
uint32_t hash = qhashmurmur3_32(key, keylen);
213
int idx = hash % tbl->range;
215
//log_error ("qhastbl:put: key=[%s], keylen=%d hash=%d, idx=%d, d=%x\n", key, keylen, hash, idx, data);
217
// find existence key
219
for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
220
if (obj->hash == hash && !strcmp(obj->key, key)) {
228
obj = (qhnobj_t *)malloc(sizeof(qhnobj_t));
234
memset((void *)obj, 0, sizeof(qhnobj_t));
236
if (tbl->slots[idx] != NULL) {
237
// insert at the beginning
238
obj->next = tbl->slots[idx];
240
tbl->slots[idx] = obj;
248
obj->value = (void *)data;
251
/* Do not do anything.
252
* Keep the first definition in place, because consider this example
253
* if we would replace the object here:
255
* def A[NX] --> A's dimension is the first variable NX (a pointer to that)
256
* def NX --> hashtable stores this variable reference
258
* write NX --> value is stored in the NX variable found in the hash table
259
* write A --> dimension found (valid first pointer) but value is not found
260
* (stored in the second reference)
261
* At this point, A's dimension variable is first NX, but the value of
262
* write NX goes to the variable found here in the hash table.
286
return qhput (tbl, key, keylen, data);
270
289
static bool put2(qhashtbl_t *tbl, const char *path, const char *name, const void *data)
274
293
genkey (path, name, &keylen, &key);
277
uint32_t hash = qhashmurmur3_32(key, keylen);
278
int idx = hash % tbl->range;
280
//log_error ("qhastbl:put: key=[%s], keylen=%d hash=%d, idx=%d, d=%x\n", key, keylen, hash, idx, data);
282
// find existence key
284
for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
285
if (obj->hash == hash && !strcmp(obj->key, key)) {
293
obj = (qhnobj_t *)malloc(sizeof(qhnobj_t));
299
memset((void *)obj, 0, sizeof(qhnobj_t));
301
if (tbl->slots[idx] != NULL) {
302
// insert at the beginning
303
obj->next = tbl->slots[idx];
305
tbl->slots[idx] = obj;
313
obj->value = (void *)data;
316
/* Do not do anything.
317
* Keep the first definition in place, because consider this example
318
* if we would replace the object here:
320
* def A[NX] --> A's dimension is the first variable NX (a pointer to that)
321
* def NX --> hashtable stores this variable reference
323
* write NX --> value is stored in the NX variable found in the hash table
324
* write A --> dimension found (valid first pointer) but value is not found
325
* (stored in the second reference)
326
* At this point, A's dimension variable is first NX, but the value of
327
* write NX goes to the variable found here in the hash table.
295
return qhput (tbl, key, keylen, data);
328
static void *qhget(qhashtbl_t *tbl, char *key, int keylen)
331
uint32_t hash = qhashmurmur3_32(key, keylen);
332
int idx = hash % tbl->range;
333
tbl->ncalls_get++; // debug
335
//log_error ("qhastbl:get: key=[%s], keylen=%d, hash=%d, idx=%d\n", fullpath, strlen(fullpath), hash, idx);
338
qhslot_t *slot = &tbl->slots[idx];
340
for (obj = slot->head; obj != NULL; obj = obj->next) {
341
if (obj->hash == hash && !strcmp(obj->key, key)) {
344
tbl->nwalks_get++; // debug: we walk one step in a chain of elements
352
if (data == NULL) errno = ENOENT;
353
//log_error ("qhastbl:get: data=%x\n", data);
365
357
static void *get(qhashtbl_t *tbl, const char *fullpath)
368
uint32_t hash = qhashmurmur3_32(fullpath, strlen(fullpath));
369
int idx = hash % tbl->range;
371
//log_error ("qhastbl:get: key=[%s], keylen=%d, hash=%d, idx=%d\n", fullpath, strlen(fullpath), hash, idx);
375
for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
376
if (obj->hash == hash && !strcmp(obj->key, fullpath)) {
386
if (data == NULL) errno = ENOENT;
387
//log_error ("qhastbl:get: data=%x\n", data);
362
int keylen = strlen(fullpath);
363
char *key = strdup (fullpath);
365
void * data = qhget (tbl, key, keylen);
392
* qhashtbl->get2(): Get a object from this table.
394
* @param tbl qhashtbl_t container pointer.
395
* @param name key name.
396
* @param size if not NULL, oject size will be stored.
397
* @param newmem whether or not to allocate memory for the data.
399
* @return a pointer of data if the key is found, otherwise returns NULL.
400
* @retval errno will be set in error condition.
401
* - ENOENT : No such key found.
402
* - EINVAL : Invalid argument.
403
* - ENOMEM : Memory allocation failure.
406
* qhashtbl_t *tbl = qHashtbl(1000);
409
* // with newmem flag unset
411
* struct myobj *obj = (struct myobj*)tbl->get(tbl, "key_name", &size, false);
413
* // with newmem flag set
415
* struct myobj *obj = (struct myobj*)tbl->get(tbl, "key_name", &size, true);
416
* if(obj != NULL) free(obj);
420
370
static void *get2(qhashtbl_t *tbl, const char *path, const char *name)
424
374
genkey (path, name, &keylen, &key);
427
uint32_t hash = qhashmurmur3_32(key, keylen);
428
int idx = hash % tbl->range;
430
//log_error ("qhastbl:get: key=[%s], keylen=%d, hash=%d, idx=%d\n", key, keylen, hash, idx);
434
for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
435
if (obj->hash == hash && !strcmp(obj->key, key)) {
445
if (data == NULL) errno = ENOENT;
446
//log_error ("qhastbl:get: data=%x\n", data);
376
void * data = qhget (tbl, key, keylen);
561
506
if (len < lenmin) lenmin = len;
562
507
if (len > lenmax) lenmax = len;
509
fprintf(out, "Hash table %p\n", tbl);
564
510
fprintf(out, "Hash table size = %d\n", tbl->range);
565
511
fprintf(out, "Number of elements = %d\n", tbl->num);
566
512
fprintf(out, "Shortest collision list size = %d\n", lenmin);
567
513
fprintf(out, "Longest collision list size = %d\n", lenmax);
514
fprintf(out, "get() calls = %d, walks = %d\n", tbl->ncalls_get, tbl->nwalks_get);
515
fprintf(out, "put() calls = %d, walks = %d\n", tbl->ncalls_put, tbl->nwalks_put);