diff options
author | Xavier Roche <xroche@users.noreply.github.com> | 2014-06-10 16:37:44 +0000 |
---|---|---|
committer | Xavier Roche <xroche@users.noreply.github.com> | 2014-06-10 16:37:44 +0000 |
commit | 93ae992d7bc8820abb5806bb46082fc5c1e29eb9 (patch) | |
tree | c8851aa17937a21c0ca1b4ece4a884a95f40186b /src/htsinthash.c | |
parent | 49dd329a09e1e2546d00f23e561dfc553a9c4e12 (diff) |
Changed hashtable types to have either opaque void*, or unions.
Diffstat (limited to 'src/htsinthash.c')
-rw-r--r-- | src/htsinthash.c | 171 |
1 files changed, 94 insertions, 77 deletions
diff --git a/src/htsinthash.c b/src/htsinthash.c index b842651..b5fa833 100644 --- a/src/htsinthash.c +++ b/src/htsinthash.c @@ -157,9 +157,9 @@ struct struct_inthash { /** How to handle values (might be NULL). **/ struct { /** free() **/ - t_inthash_freehandler free; + t_inthash_value_freehandler free; /** opaque argument **/ - void *arg; + inthash_opaque arg; } value; /** How to handle names (might be NULL). **/ @@ -167,13 +167,13 @@ struct struct_inthash { /** strdup() **/ t_inthash_duphandler dup; /** free() **/ - t_inthash_freehandler free; + t_inthash_key_freehandler free; /** hash **/ t_inthash_hasheshandler hash; /** comparison **/ t_inthash_cmphandler equals; /** opaque argument **/ - void *arg; + inthash_opaque arg; } key; /** How to handle fatal assertions (might be NULL). **/ @@ -183,9 +183,9 @@ struct struct_inthash { /** abort() **/ t_inthash_asserthandler fatal; /** opaque argument **/ - void *arg; + inthash_opaque arg; /** hashtable name for logging **/ - const char *name; + inthash_key_const name; } error; /** How to handle pretty-print (debug) (might be NULL). **/ @@ -195,7 +195,7 @@ struct struct_inthash { /** value print() **/ t_inthash_printvaluehandler value; /** opaque argument **/ - void *arg; + inthash_opaque arg; } print; } custom; }; @@ -272,7 +272,7 @@ static void inthash_fail(const char* exp, const char* file, int line) { /* assert failed handler. */ static void inthash_assert_failed(const inthash hashtable, const char* exp, const char* file, int line) { - const char *name = inthash_get_name(hashtable); + const char *const name = inthash_get_name(hashtable); inthash_crit(hashtable, "hashtable %s: %s failed at %s:%d", name != NULL ? name : "<unknown>", exp, file, line); if (hashtable != NULL && hashtable->custom.error.fatal != NULL) { @@ -311,7 +311,7 @@ const char* inthash_get_name(inthash hashtable) { } static void inthash_log_stats(inthash hashtable) { - const char *name = inthash_get_name(hashtable); + const char *const name = inthash_get_name(hashtable); inthash_info(hashtable, "hashtable %s%s%ssummary: " "size=%"UINT_64_FORMAT" (lg2=%"UINT_64_FORMAT") " "used=%"UINT_64_FORMAT" " @@ -352,20 +352,21 @@ static void inthash_log_stats(inthash hashtable) { ); } -inthash_keys inthash_hash_value(const char *value) { +/* default hash function when key is a regular C-string */ +inthash_hashkeys inthash_hash_string(const char *name) { #if HTS_INTHASH_USES_MD5 == 1 /* compute a regular MD5 and extract two 32-bit integers */ MD5_CTX ctx; union { unsigned char md5digest[16]; - inthash_keys mhashes[2]; - inthash_keys hashes; + inthash_hashkeys mhashes[2]; + inthash_hashkeys hashes; } u; /* compute MD5 */ MD5Init(&ctx, 0); - MD5Update(&ctx, (const unsigned char *) value, - (unsigned int) strlen(value)); + MD5Update(&ctx, (const unsigned char *) name, + (unsigned int) strlen(name)); MD5Final(u.md5digest, &ctx); /* mix mix mix */ @@ -381,9 +382,9 @@ inthash_keys inthash_hash_value(const char *value) { #elif (defined(HTS_INTHASH_USES_MURMUR)) union { uint32_t result[4]; - inthash_keys hashes; + inthash_hashkeys hashes; } u; - MurmurHash3_x86_128(value, (const int) strlen(value), + MurmurHash3_x86_128(name, (const int) strlen(name), 42, &u.result) ; /* mix mix mix */ @@ -400,7 +401,7 @@ inthash_keys inthash_hash_value(const char *value) { /* compute two Fowler-Noll-Vo hashes (64-bit FNV-1 variant) ; each 64-bit hash being XOR-folded into a single 32-bit hash. */ size_t i; - inthash_keys hashes; + inthash_hashkeys hashes; uint64_t h1, h2; /* FNV-1, 64-bit. */ @@ -410,8 +411,8 @@ inthash_keys inthash_hash_value(const char *value) { /* compute the hashes ; second variant is using xored data */ h1 = FNV1_OFFSET_BASIS; h2 = ~FNV1_OFFSET_BASIS; - for(i = 0 ; value[i] != '\0' ; i++) { - const unsigned char c1 = value[i]; + for(i = 0 ; name[i] != '\0' ; i++) { + const unsigned char c1 = name[i]; const unsigned char c2 = ~c1; h1 = ( h1 * FNV1_PRIME ) ^ c1; h2 = ( h2 * FNV1_PRIME ) ^ c2; @@ -433,10 +434,10 @@ inthash_keys inthash_hash_value(const char *value) { #endif } -static INTHASH_INLINE inthash_keys inthash_calc_hashes(inthash hashtable, - const char *value) { +static INTHASH_INLINE inthash_hashkeys inthash_calc_hashes(inthash hashtable, + inthash_key_const value) { return hashtable->custom.key.hash == NULL - ? inthash_hash_value(value) + ? inthash_hash_string(value) : hashtable->custom.key.hash(hashtable->custom.key.arg, value); } @@ -447,16 +448,17 @@ static INTHASH_INLINE int inthash_is_free(const inthash hashtable, size_t pos) { /* compare two keys ; by default using strcmp() */ static INTHASH_INLINE int inthash_equals(inthash hashtable, - const char *a, const char *b) { + inthash_key_const a, + inthash_key_const b) { return hashtable->custom.key.equals == NULL - ? strcmp(a, b) == 0 + ? strcmp((const char*) a, (const char*) b) == 0 : hashtable->custom.key.equals(hashtable->custom.key.arg, a, b); } static INTHASH_INLINE int inthash_matches_(inthash hashtable, const inthash_item *const item, - const char *name, - const inthash_keys *hashes) { + inthash_key_const name, + const inthash_hashkeys *hashes) { return item->name != NULL && item->hashes.hash1 == hashes->hash1 && item->hashes.hash2 == hashes->hash2 @@ -464,8 +466,8 @@ static INTHASH_INLINE int inthash_matches_(inthash hashtable, } static INTHASH_INLINE int inthash_matches(inthash hashtable, size_t pos, - const char *name, - const inthash_keys *hashes) { + inthash_key_const name, + const inthash_hashkeys *hashes) { const inthash_item *const item = &hashtable->items[pos]; return inthash_matches_(hashtable, item, name, hashes); } @@ -589,7 +591,7 @@ static void inthash_realloc_pool(inthash hashtable, size_t capacity) { /* recompute string address */ #define RECOMPUTE_STRING(S) do { \ if (S != NULL && S != the_empty_string) { \ - const size_t offset = (S) - oldbase; \ + const size_t offset = (const char*) (S) - oldbase; \ inthash_assert(hashtable, offset < hashtable->pool.capacity); \ S = &hashtable->pool.buffer[offset]; \ count++; \ @@ -611,7 +613,9 @@ static void inthash_realloc_pool(inthash hashtable, size_t capacity) { (uint64_t) count, (uint64_t) hashtable->pool.capacity); } -static char* inthash_dup_name_internal(inthash hashtable, const char *name) { +static inthash_key inthash_dup_name_internal(inthash hashtable, + inthash_key_const name_) { + const char *const name = (const char*) name_; const size_t len = strlen(name) + 1; char *s; @@ -643,7 +647,8 @@ static char* inthash_dup_name_internal(inthash hashtable, const char *name) { } /* duplicate a key. default is to use the internal pool. */ -static INTHASH_INLINE char* inthash_dup_name(inthash hashtable, const char *name) { +static INTHASH_INLINE inthash_key inthash_dup_name(inthash hashtable, + inthash_key_const name) { return hashtable->custom.key.dup == NULL ? inthash_dup_name_internal(hashtable, name) : hashtable->custom.key.dup(hashtable->custom.key.arg, name); @@ -651,7 +656,8 @@ static INTHASH_INLINE char* inthash_dup_name(inthash hashtable, const char *name /* internal pool free handler. note: pointer must have been kicked from the pool first */ -static void inthash_free_key_internal(inthash hashtable, char *name) { +static void inthash_free_key_internal(inthash hashtable, inthash_key name_) { + char *const name = (char*) name_; const size_t len = strlen(name) + 1; /* see inthash_dup_name_internal() handling */ @@ -678,7 +684,7 @@ static void inthash_free_key_internal(inthash hashtable, char *name) { /* free a key. default is to use the internal pool. note: pointer must have been kicked from the pool first */ -static void inthash_free_key(inthash hashtable, char *name) { +static void inthash_free_key(inthash hashtable, inthash_key name) { if (hashtable->custom.key.free == NULL) { inthash_free_key_internal(hashtable, name); } else { @@ -687,17 +693,17 @@ static void inthash_free_key(inthash hashtable, char *name) { } static INTHASH_INLINE size_t inthash_hash_to_pos_(size_t lg_size, - inthash_key hash) { - const inthash_key mask = POW2(lg_size) - 1; + inthash_hashkey hash) { + const inthash_hashkey mask = POW2(lg_size) - 1; return hash & mask; } static INTHASH_INLINE size_t inthash_hash_to_pos(const inthash hashtable, - inthash_key hash) { + inthash_hashkey hash) { return inthash_hash_to_pos_(hashtable->lg_size, hash); } -int inthash_read_pvoid(inthash hashtable, const char *name, void **pvalue) { +int inthash_read_pvoid(inthash hashtable, inthash_key_const name, void **pvalue) { inthash_value value = INTHASH_VALUE_NULL; const int ret = inthash_read_value(hashtable, name, (pvalue != NULL) ? &value : NULL); @@ -706,35 +712,36 @@ int inthash_read_pvoid(inthash hashtable, const char *name, void **pvalue) { return ret; } -int inthash_write_pvoid(inthash hashtable, const char *name, void *pvalue) { +int inthash_write_pvoid(inthash hashtable, inthash_key_const name, void *pvalue) { inthash_value value = INTHASH_VALUE_NULL; value.ptr = pvalue; return inthash_write_value(hashtable, name, value); } -void inthash_add_pvoid(inthash hashtable, const char *name, void *pvalue) { +void inthash_add_pvoid(inthash hashtable, inthash_key_const name, void *pvalue) { inthash_value value = INTHASH_VALUE_NULL; value.ptr = pvalue; inthash_write_value(hashtable, name, value); } -int inthash_write(inthash hashtable, const char *name, intptr_t intvalue) { +int inthash_write(inthash hashtable, inthash_key_const name, intptr_t intvalue) { inthash_value value = INTHASH_VALUE_NULL; value.intg = intvalue; return inthash_write_value(hashtable, name, value); } -static void inthash_default_free_handler(void *arg, void *value) { - if (value) - free(value); +static void inthash_default_free_handler(inthash_opaque arg, + inthash_value value) { + if (value.ptr != NULL) + free(value.ptr); } static void inthash_del_value_(inthash hashtable, inthash_value *pvalue) { if (hashtable->custom.value.free != NULL) - hashtable->custom.value.free(hashtable->custom.value.arg, pvalue->ptr); + hashtable->custom.value.free(hashtable->custom.value.arg, *pvalue); pvalue->ptr = NULL; } @@ -743,8 +750,8 @@ static void inthash_del_value(inthash hashtable, size_t pos) { } static void inthash_del_name(inthash hashtable, inthash_item *item) { - const inthash_keys nullHash = INTHASH_KEYS_NULL; - char *const name = item->name; + const inthash_hashkeys nullHash = INTHASH_KEYS_NULL; + char *const name = (char*) item->name; item->name = NULL; /* there must be no reference remaining */ item->hashes = nullHash; /* free after detach (we may compact the pool) */ @@ -759,11 +766,11 @@ static void inthash_del_item(inthash hashtable, inthash_item *pitem) { static int inthash_add_item_(inthash hashtable, inthash_item item); /* Write (add or replace) a value in the hashtable. */ -static int inthash_write_value_(inthash hashtable, const char *name, +static int inthash_write_value_(inthash hashtable, inthash_key_const name, inthash_value value) { inthash_item item; size_t pos; - const inthash_keys hashes = inthash_calc_hashes(hashtable, name); + const inthash_hashkeys hashes = inthash_calc_hashes(hashtable, name); /* Statistics */ hashtable->stats.write_count++; @@ -808,9 +815,17 @@ static int inthash_write_value_(inthash hashtable, const char *name, return inthash_add_item_(hashtable, item); } +/* Return the string representation of a key */ +static const char* inthash_print_key(inthash hashtable, + inthash_key_const name) { + return hashtable->custom.print.key != NULL + ? hashtable->custom.print.key(hashtable->custom.print.arg, name) + : (const char*) name; +} + /* Add a new item in the hashtable. The item SHALL NOT be alreasy present. */ static int inthash_add_item_(inthash hashtable, inthash_item item) { - inthash_key cuckoo_hash, initial_cuckoo_hash; + inthash_hashkey cuckoo_hash, initial_cuckoo_hash; size_t loops; size_t pos; @@ -831,7 +846,8 @@ static int inthash_add_item_(inthash hashtable, inthash_item item) { cuckoo_hash = initial_cuckoo_hash = item.hashes.hash1; inthash_trace(hashtable, "debug:collision with '%s' at %"UINT_64_FORMAT" (%x)", - item.name, (uint64_t) pos, cuckoo_hash); + inthash_print_key(hashtable, item.name), + (uint64_t) pos, cuckoo_hash); } } @@ -841,7 +857,8 @@ static int inthash_add_item_(inthash hashtable, inthash_item item) { inthash_trace(hashtable, "\tdebug:placing cuckoo '%s' at %"UINT_64_FORMAT" (%x)", - item.name, (uint64_t) pos, cuckoo_hash); + inthash_print_key(hashtable, item.name), + (uint64_t) pos, cuckoo_hash); /* place at alternate free position ? */ if (inthash_is_free(hashtable, pos)) { @@ -911,7 +928,7 @@ static int inthash_add_item_(inthash hashtable, inthash_item item) { "stash[%u]: key='%s' value='%s' pos1=%d pos2=%d hash1=%04x hash2=%04x", (int) i, hashtable->custom.print.key(hashtable->custom.print.arg, item->name), - hashtable->custom.print.value(hashtable->custom.print.arg, item->value.ptr), + hashtable->custom.print.value(hashtable->custom.print.arg, item->value), (int) pos1, (int) pos2, item->hashes.hash1, item->hashes.hash2); if (!inthash_is_free(hashtable, pos1)) { @@ -921,7 +938,7 @@ static int inthash_add_item_(inthash hashtable, inthash_item item) { inthash_crit(hashtable, "\t.. collisionning with key='%s' value='%s' pos1=%d pos2=%d hash1=%04x hash2=%04x", hashtable->custom.print.key(hashtable->custom.print.arg, item->name), - hashtable->custom.print.value(hashtable->custom.print.arg, item->value.ptr), + hashtable->custom.print.value(hashtable->custom.print.arg, item->value), (int) pos1, (int) pos2, item->hashes.hash1, item->hashes.hash2); } else { @@ -934,7 +951,7 @@ static int inthash_add_item_(inthash hashtable, inthash_item item) { inthash_crit(hashtable, "\t.. collisionning with key='%s' value='%s' pos1=%d pos2=%d hash1=%04x hash2=%04x", hashtable->custom.print.key(hashtable->custom.print.arg, item->name), - hashtable->custom.print.value(hashtable->custom.print.arg, item->value.ptr), + hashtable->custom.print.value(hashtable->custom.print.arg, item->value), (int) pos1, (int) pos2, item->hashes.hash1, item->hashes.hash2); } else { @@ -960,7 +977,7 @@ static int inthash_add_item_(inthash hashtable, inthash_item item) { } } -int inthash_write_value(inthash hashtable, const char *name, +int inthash_write_value(inthash hashtable, inthash_key_const name, inthash_value value) { /* replace of add item */ const int ret = inthash_write_value_(hashtable, name, value); @@ -1020,7 +1037,7 @@ int inthash_write_value(inthash hashtable, const char *name, /* relocate lower half items when needed */ for(i = 0 ; i < prev_size ; i++) { if (!inthash_is_free(hashtable, i)) { - const inthash_keys *const hashes = &hashtable->items[i].hashes; + const inthash_hashkeys *const hashes = &hashtable->items[i].hashes; /* currently at old position 1 */ if (inthash_hash_to_pos_(prev_power, hashes->hash1) == i) { @@ -1087,7 +1104,7 @@ int inthash_write_value(inthash hashtable, const char *name, return ret; } -void inthash_add(inthash hashtable, const char *name, intptr_t intvalue) { +void inthash_add(inthash hashtable, inthash_key_const name, intptr_t intvalue) { inthash_value value = INTHASH_VALUE_NULL; memset(&value, 0, sizeof(value)); @@ -1095,7 +1112,7 @@ void inthash_add(inthash hashtable, const char *name, intptr_t intvalue) { inthash_write_value(hashtable, name, value); } -int inthash_read(inthash hashtable, const char *name, intptr_t * intvalue) { +int inthash_read(inthash hashtable, inthash_key_const name, intptr_t * intvalue) { inthash_value value = INTHASH_VALUE_NULL; int ret = inthash_read_value(hashtable, name, (intvalue != NULL) ? &value : NULL); @@ -1105,8 +1122,8 @@ int inthash_read(inthash hashtable, const char *name, intptr_t * intvalue) { } static inthash_value* inthash_read_value_(inthash hashtable, - const char *name) { - const inthash_keys hashes = inthash_calc_hashes(hashtable, name); + inthash_key_const name) { + const inthash_hashkeys hashes = inthash_calc_hashes(hashtable, name); size_t pos; /* found at position 1 ? */ @@ -1136,7 +1153,7 @@ static inthash_value* inthash_read_value_(inthash hashtable, return NULL; } -int inthash_read_value(inthash hashtable, const char *name, +int inthash_read_value(inthash hashtable, inthash_key_const name, inthash_value * pvalue) { inthash_value* const value = inthash_read_value_(hashtable, name); if (value != NULL) { @@ -1148,7 +1165,7 @@ int inthash_read_value(inthash hashtable, const char *name, return 0; } -static size_t inthash_inc_(inthash hashtable, const char *name, +static size_t inthash_inc_(inthash hashtable, inthash_key_const name, size_t inc) { inthash_value* const value = inthash_read_value_(hashtable, name); if (value != NULL) { @@ -1162,20 +1179,20 @@ static size_t inthash_inc_(inthash hashtable, const char *name, } } -int inthash_inc(inthash hashtable, const char *name) { +int inthash_inc(inthash hashtable, inthash_key_const name) { return (int) inthash_inc_(hashtable, name, 1); } -int inthash_dec(inthash hashtable, const char *name) { +int inthash_dec(inthash hashtable, inthash_key_const name) { return (int) inthash_inc_(hashtable, name, (size_t) -1); } -int inthash_exists(inthash hashtable, const char *name) { +int inthash_exists(inthash hashtable, inthash_key_const name) { return inthash_read_value(hashtable, name, NULL); } -static int inthash_remove_(inthash hashtable, const char *name, - const inthash_keys *hashes, size_t *removed) { +static int inthash_remove_(inthash hashtable, inthash_key_const name, + const inthash_hashkeys *hashes, size_t *removed) { size_t pos; /* found at position 1 ? */ @@ -1217,8 +1234,8 @@ static int inthash_remove_(inthash hashtable, const char *name, return 0; } -int inthash_remove(inthash hashtable, const char *name) { - const inthash_keys hashes = inthash_calc_hashes(hashtable, name); +int inthash_remove(inthash hashtable, inthash_key_const name) { + const inthash_hashkeys hashes = inthash_calc_hashes(hashtable, name); size_t removed; const int ret = inthash_remove_(hashtable, name, &hashes, &removed); @@ -1256,7 +1273,7 @@ int inthash_remove(inthash hashtable, const char *name) { return ret; } -int inthash_readptr(inthash hashtable, const char *name, intptr_t * value) { +int inthash_readptr(inthash hashtable, inthash_key_const name, intptr_t * value) { int ret; *value = 0; @@ -1324,23 +1341,23 @@ void inthash_value_is_malloc(inthash hashtable, int flag) { } } -void inthash_set_name(inthash hashtable, const char *name) { +void inthash_set_name(inthash hashtable, inthash_key_const name) { hashtable->custom.error.name = name; } void inthash_value_set_value_handler(inthash hashtable, - t_inthash_freehandler free, - void *arg) { + t_inthash_value_freehandler free, + inthash_opaque arg) { hashtable->custom.value.free = free; hashtable->custom.value.arg = arg; } void inthash_value_set_key_handler(inthash hashtable, t_inthash_duphandler dup, - t_inthash_freehandler free, + t_inthash_key_freehandler free, t_inthash_hasheshandler hash, t_inthash_cmphandler equals, - void *arg) { + inthash_opaque arg) { /* dup and free must be consistent */ inthash_assert(hashtable, ( dup == NULL ) == ( free == NULL ) ); hashtable->custom.key.dup = dup; @@ -1353,7 +1370,7 @@ void inthash_value_set_key_handler(inthash hashtable, void inthash_set_assert_handler(inthash hashtable, t_inthash_loghandler log, t_inthash_asserthandler fatal, - void *arg) { + inthash_opaque arg) { hashtable->custom.error.log = log; hashtable->custom.error.fatal = fatal; hashtable->custom.error.arg = arg; @@ -1362,7 +1379,7 @@ void inthash_set_assert_handler(inthash hashtable, void inthash_set_print_handler(inthash hashtable, t_inthash_printkeyhandler key, t_inthash_printvaluehandler value, - void *arg) { + inthash_opaque arg) { hashtable->custom.print.key = key; hashtable->custom.print.value = value; hashtable->custom.print.arg = arg; |