From 8aa3749cfb96c2dcc0dd58caf87ff9b9786fd19d Mon Sep 17 00:00:00 2001 From: Al Date: Wed, 8 Feb 2017 19:01:13 -0500 Subject: [PATCH] [utils] some convenience functions for generic hashtables (incr, get, etc) --- src/collections.h | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/src/collections.h b/src/collections.h index 2691ad3f..2401d961 100644 --- a/src/collections.h +++ b/src/collections.h @@ -18,6 +18,7 @@ // Maps KHASH_MAP_INIT_INT(int_uint32, uint32_t) +KHASH_MAP_INIT_INT64(int64_uint32, uint32_t) #define kh_char_hash_func(key) (uint32_t)(key) #define kh_char_hash_equal(a, b) ((a) == (b)) @@ -33,6 +34,7 @@ KHASH_MAP_INIT_STR(str_str, char *) // Sets KHASH_SET_INIT_INT(int_set) +KHASH_SET_INIT_INT64(int64_set) KHASH_SET_INIT_STR(str_set) // Vectors @@ -84,4 +86,115 @@ KSORT_INIT_STR KHASH_SORT_BY_VALUE(str_uint32, char *, uint32_t, uint32_array) KHASH_SORT_BY_VALUE(str_double, char *, double, double_array) +#define KHASH_STR_GET(name, key_type, val_type) \ + static bool name##_hash_get(khash_t(name) *h, key_type *key, val_type *val) { \ + khiter_t k; \ + k = kh_get(name, h, (const key_type)key); \ + if (k != kh_end(h)) { \ + *val = kh_value(h, k); \ + return true; \ + } \ + return false; \ + } + +KHASH_STR_GET(str_uint32, kh_cstr_t, uint32_t) + +#define KHASH_STR_INCR(name, val_type) \ + static bool name##_hash_incr_by_exists(khash_t(name) *h, const char *key, val_type val, bool *exists) { \ + khiter_t k; \ + int ret = 0; \ + k = kh_get(name, h, key); \ + if (k == kh_end(h)) { \ + char *key_copy = strdup(key); \ + if (key_copy == NULL) { \ + return false; \ + } \ + k = kh_put(name, h, key_copy, &ret); \ + if (ret < 0) { \ + free(key_copy); \ + return false; \ + } \ + kh_value(h, k) = (val_type)0; \ + *exists = false; \ + } else { \ + *exists = true; \ + } \ + kh_value(h, k) += val; \ + return true; \ + } \ + static bool name##_hash_incr_exists(khash_t(name) *h, const char *key, bool *exists) { \ + return name##_hash_incr_by_exists(h, key, (val_type)1, exists); \ + } \ + static bool name##_hash_incr_by(khash_t(name) *h, const char *key, val_type val) { \ + bool exists = false; \ + return name##_hash_incr_by_exists(h, key, val, &exists); \ + } \ + static bool name##_hash_incr(khash_t(name) *h, const char *key) { \ + bool exists = false; \ + return name##_hash_incr_by_exists(h, key, (val_type)1, &exists); \ + } + +KHASH_STR_INCR(str_uint32, uint32_t) + +#define KHASH_STR_TO_ID(name, val_type) \ + static bool name##_hash_to_id_exists(khash_t(name) *h, const char *key, val_type *val, bool *exists) { \ + khiter_t k; \ + int ret = 0; \ + k = kh_get(name, h, key); \ + if (k == kh_end(h)) { \ + char *key_copy = strdup(key); \ + if (key_copy == NULL) { \ + return false; \ + } \ + k = kh_put(name, h, key_copy, &ret); \ + if (ret < 0) { \ + free(key_copy); \ + return false; \ + } \ + kh_value(h, k) = (val_type)kh_size(h); \ + *exists = false; \ + } \ + *val = kh_value(h, k); \ + return true; \ + } \ + static bool name##_hash_to_id(khash_t(name) *h, const char *key, val_type *val) { \ + bool exists = false; \ + return name##_hash_to_id_exists(h, key, val, &exists); \ + } + +KHASH_STR_TO_ID(str_uint32, uint32_t) + +#define KHASH_INCR(name, key_type, val_type) \ + static bool name##_hash_incr_by_exists(khash_t(name) *h, key_type key, val_type val, bool *exists) { \ + khiter_t k; \ + int ret = 0; \ + k = kh_get(name, h, key); \ + if (k == kh_end(h)) { \ + k = kh_put(name, h, key, &ret); \ + if (ret < 0) { \ + return false; \ + } \ + kh_value(h, k) = (val_type)0; \ + *exists = false; \ + } else { \ + *exists = true; \ + } \ + kh_value(h, k) += val; \ + return true; \ + } \ + static bool name##_hash_incr_exists(khash_t(name) *h, key_type key, bool *exists) { \ + return name##_hash_incr_by_exists(h, key, (val_type)1, exists); \ + } \ + static bool name##_hash_incr_by(khash_t(name) *h, key_type key, val_type val) { \ + bool exists = false; \ + return name##_hash_incr_by_exists(h, key, val, &exists); \ + } \ + static bool name##_hash_incr(khash_t(name) *h, key_type key) { \ + bool exists = false; \ + return name##_hash_incr_by_exists(h, key, (val_type)1, &exists); \ + } + +KHASH_INCR(int_uint32, khint32_t, uint32_t) +KHASH_INCR(int64_uint32, khint64_t, uint32_t) + #endif