Skip to content

Instantly share code, notes, and snippets.

@bnm3k
Created April 25, 2020 14:57
Show Gist options
  • Save bnm3k/4676a267e5dfce65732d0b98c9592a2c to your computer and use it in GitHub Desktop.
Save bnm3k/4676a267e5dfce65732d0b98c9592a2c to your computer and use it in GitHub Desktop.
A quick demonstration on using khash to store string values allocated on the heap, and eventually freeing them after use
#include "khash.h"
#include <stdbool.h>
#include <stdio.h>
void gen_rand_string(char *buf, size_t buf_len, bool should_randomize_str_len) {
static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
size_t str_len = buf_len - 1;
if (should_randomize_str_len)
str_len = (rand() % str_len) + 1;
for (size_t i = 0; i < str_len; i++) {
int key = rand() % (int)(sizeof(charset) - 1);
buf[i] = charset[key];
}
buf[str_len] = '\0';
}
KHASH_MAP_INIT_STR(str_to_str, char *)
int main() {
const size_t key_buf_len = 4; //max_key_len = key_buf_len - 1
const size_t val_buf_len = 31; //max_val_len = val_buf_len - 1
const bool should_randomize_key_len = false;
const bool should_randomize_val_len = true;
const unsigned max_items_to_insert = 10000;
khash_t(str_to_str) *foo_hash_table = kh_init(str_to_str);
unsigned items_inserted = 0;
for (unsigned i = 0; i < max_items_to_insert; i++) {
int absent;
char *key_buf = calloc(key_buf_len, sizeof(char));
char *val_buf = calloc(val_buf_len, sizeof(char));
/* gen key & val */
gen_rand_string(key_buf, key_buf_len, should_randomize_key_len);
gen_rand_string(val_buf, val_buf_len, should_randomize_val_len);
/* insert key */
khiter_t new_item_it = kh_put(str_to_str, foo_hash_table, key_buf, &absent);
/*
* insert val
* if key already present, kh_put places 0 into ret var
* if key not present, kh_put places a non-zero value into ret var
*/
if (absent) {
kh_key(foo_hash_table, new_item_it) = key_buf;
kh_val(foo_hash_table, new_item_it) = val_buf;
items_inserted++;
} else {
free(key_buf);
free(val_buf);
}
}
printf("%d insertion attempts; %d duplicates; %d keys\n\n", max_items_to_insert, max_items_to_insert - items_inserted, items_inserted);
/* iterate over items method 1, print 5 items only */
const char *k, *v;
int i = 5;
kh_foreach(foo_hash_table, k, v, {
fprintf(stdout, "%s -> %s\n", k, v);
if (--i < 0) break;
});
/* free items then free table */
/* also, iterate over items method 2 */
for (khiter_t it = kh_begin(foo_hash_table); it != kh_end(foo_hash_table); ++it) {
if (kh_exist(foo_hash_table, it)) {
free((void *)kh_key(foo_hash_table, it));
free((void *)kh_val(foo_hash_table, it));
}
}
kh_destroy(str_to_str, foo_hash_table);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment