diff options
-rw-r--r-- | src/htsinthash.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/src/htsinthash.c b/src/htsinthash.c index a25bd85..9a0f0c5 100644 --- a/src/htsinthash.c +++ b/src/htsinthash.c @@ -218,6 +218,9 @@ static void inthash_fail(const char* exp, const char* file, int line) { /* 2**X */ #define POW2(X) ( (size_t) 1 << (X) ) +/* the empty string for the string pool */ +static char the_empty_string[1] = { 0 }; + /* Logging */ static void inthash_log(const inthash hashtable, const char *format, ...) HTS_PRINTF_FUN(2, 3) { @@ -386,19 +389,28 @@ static void inthash_compact_pool(inthash hashtable, size_t capacity) { /* relocate a string on a different pool */ #define RELOCATE_STRING(S) do { \ - if (S != NULL) { \ + if (S != NULL && S != the_empty_string) { \ + const char *const src = (S); \ + char *const dest = \ + &hashtable->pool.buffer[hashtable->pool.size]; \ const size_t capacity = hashtable->pool.capacity; \ - const char *const src = S; \ - char *const dest = hashtable->pool.buffer; \ - size_t i, j; \ - for(i = 0, j = hashtable->pool.size \ - ; src[i] != '\0' ; i++, j++) { \ - inthash_assert(j < capacity); \ - dest[j] = src[i]; \ + char *const max_dest = \ + &hashtable->pool.buffer[capacity]; \ + /* copy string */ \ + inthash_assert(dest < max_dest); \ + dest[0] = src[0]; \ + { \ + size_t i; \ + for(i = 1 ; src[i - 1] != '\0' ; i++) { \ + inthash_assert(&dest[i] < max_dest); \ + dest[i] = src[i]; \ + } \ } \ - inthash_assert(j < capacity); \ - dest[j++] = '\0'; \ - hashtable->pool.size = j; \ + /* update source */ \ + S = dest; \ + /* update pool size */ \ + hashtable->pool.size += i; \ + assert(hashtable->pool.size <= capacity); \ count++; \ } \ } while(0) @@ -461,8 +473,9 @@ static void inthash_realloc_pool(inthash hashtable, size_t capacity) { /* recompute string address */ #define RECOMPUTE_STRING(S) do { \ - if (S != NULL) { \ + if (S != NULL && S != the_empty_string) { \ const size_t offset = (S) - oldbase; \ + assert(offset < hashtable->pool.capacity); \ S = &hashtable->pool.buffer[offset]; \ count++; \ } \ @@ -483,9 +496,6 @@ static void inthash_realloc_pool(inthash hashtable, size_t capacity) { (uint64_t) count, (uint64_t) hashtable->pool.capacity); } -/* the empty string for the string pool */ -static char the_empty_string[1] = { 0 }; - static char* inthash_dup_name_internal(inthash hashtable, const char *name) { const size_t len = strlen(name) + 1; char *s; @@ -859,6 +869,8 @@ int inthash_write_value(inthash hashtable, const char *name, memcpy(&stash, hashtable->stash.items, sizeof(hashtable->stash.items)); hashtable->stash.size = 0; + /* FIXME do not modify the string pool by duping the keys */ + /* insert all items */ for(i = 0 ; i < old_size ; i++) { const int ret = inthash_write_value_(hashtable, stash[i].name, |