diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/htsinthash.c | 137 |
1 files changed, 77 insertions, 60 deletions
diff --git a/src/htsinthash.c b/src/htsinthash.c index a18ed23..d6a6e55 100644 --- a/src/htsinthash.c +++ b/src/htsinthash.c @@ -285,53 +285,8 @@ static HTS_INLINE int inthash_matches(const inthash hashtable, size_t pos, return inthash_matches_(item, name, hashes); } -/* realloc (expand) string pool ; does not change the compacity */ -static void inthash_realloc_pool(inthash hashtable) { - const size_t hash_size = POW2(hashtable->lg_size); - char *const oldbase = hashtable->pool.buffer; - size_t i; - size_t count = 0; - - /* statistics */ - hashtable->stats.pool_realloc_count++; - - /* realloc */ - hashtable->pool.buffer = realloc(hashtable->pool.buffer, - hashtable->pool.capacity); - if (hashtable->pool.buffer == NULL) { - inthash_crit(hashtable, - "** hashtable string pool allocation error: could not allocate " - "%"UINT_64_FORMAT" bytes", - (uint64_t) hashtable->pool.capacity); - inthash_assert(! "hashtable string pool allocation error"); - } - - /* recompute string address */ -#define RECOMPUTE_STRING(S) do { \ - if (S != NULL) { \ - const size_t offset = (S) - oldbase; \ - S = &hashtable->pool.buffer[offset]; \ - count++; \ - } \ -} while(0) - - /* recompute */ - for(i = 0 ; i < hash_size ; i++) { - RECOMPUTE_STRING(hashtable->items[i].name); - } - for(i = 0 ; i < hashtable->stash.size ; i++) { - RECOMPUTE_STRING(hashtable->stash.items[i].name); - } - -#undef RECOMPUTE_STRING - - inthash_debug(hashtable, "reallocated string pool for " - "%"UINT_64_FORMAT" strings: %"UINT_64_FORMAT" bytes", - (uint64_t) count, (uint64_t) hashtable->pool.capacity); -} - /* compact string pool ; does not change the capacity */ -static void inthash_compact_pool(inthash hashtable) { +static void inthash_compact_pool(inthash hashtable, size_t capacity) { const size_t hash_size = POW2(hashtable->lg_size); size_t i; char* old_pool = hashtable->pool.buffer; @@ -341,6 +296,11 @@ static void inthash_compact_pool(inthash hashtable) { /* statistics */ hashtable->stats.pool_compact_count++; + /* change capacity now */ + if (hashtable->pool.capacity != capacity) { + hashtable->pool.capacity = capacity; + } + /* realloc */ hashtable->pool.buffer = malloc(hashtable->pool.capacity); hashtable->pool.size = 0; @@ -356,13 +316,17 @@ static void inthash_compact_pool(inthash hashtable) { /* relocate a string on a different pool */ #define RELOCATE_STRING(S) do { \ if (S != NULL) { \ - const size_t len = strlen(S) + 1; \ - inthash_assert(hashtable->pool.size + len \ - <= hashtable->pool.capacity); \ - memcpy(&hashtable->pool.buffer[hashtable->pool.size], \ - S, len); \ - S = &hashtable->pool.buffer[hashtable->pool.size]; \ - hashtable->pool.size += len; \ + 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]; \ + } \ + dest[j++] = '\0'; \ + hashtable->pool.size = j; \ count++; \ } \ } while(0) @@ -390,19 +354,72 @@ static void inthash_compact_pool(inthash hashtable) { (uint64_t) hashtable->pool.size); } +/* realloc (expand) string pool ; does not change the compacity */ +static void inthash_realloc_pool(inthash hashtable, size_t capacity) { + const size_t hash_size = POW2(hashtable->lg_size); + char *const oldbase = hashtable->pool.buffer; + size_t i; + size_t count = 0; + + /* compact instead ? */ + if (hashtable->pool.used < ( hashtable->pool.size*3 ) / 4) { + inthash_compact_pool(hashtable, capacity); + return ; + } + + /* statistics */ + hashtable->stats.pool_realloc_count++; + + /* change capacity now */ + hashtable->pool.capacity = capacity; + + /* realloc */ + hashtable->pool.buffer = realloc(hashtable->pool.buffer, + hashtable->pool.capacity); + if (hashtable->pool.buffer == NULL) { + inthash_crit(hashtable, + "** hashtable string pool allocation error: could not allocate " + "%"UINT_64_FORMAT" bytes", + (uint64_t) hashtable->pool.capacity); + inthash_assert(! "hashtable string pool allocation error"); + } + + /* recompute string address */ +#define RECOMPUTE_STRING(S) do { \ + if (S != NULL) { \ + const size_t offset = (S) - oldbase; \ + S = &hashtable->pool.buffer[offset]; \ + count++; \ + } \ +} while(0) + + /* recompute */ + for(i = 0 ; i < hash_size ; i++) { + RECOMPUTE_STRING(hashtable->items[i].name); + } + for(i = 0 ; i < hashtable->stash.size ; i++) { + RECOMPUTE_STRING(hashtable->stash.items[i].name); + } + +#undef RECOMPUTE_STRING + + inthash_debug(hashtable, "reallocated string pool for " + "%"UINT_64_FORMAT" strings: %"UINT_64_FORMAT" bytes", + (uint64_t) count, (uint64_t) hashtable->pool.capacity); +} + static char* inthash_dup_name(inthash hashtable, const char *name) { const size_t len = strlen(name) + 1; char *s; if (hashtable->pool.capacity - hashtable->pool.size < len) { - if (hashtable->pool.capacity == 0) { - hashtable->pool.capacity = MIN_POOL_CAPACITY; - } - for( ; hashtable->pool.capacity - hashtable->pool.size < len - ; hashtable->pool.capacity <<= 1) ; - inthash_realloc_pool(hashtable); + size_t capacity; + for(capacity = MIN_POOL_CAPACITY ; capacity < hashtable->pool.size + len + ; capacity <<= 1) ; + inthash_realloc_pool(hashtable, capacity); } + assert(len + hashtable->pool.size <= hashtable->pool.capacity); s = &hashtable->pool.buffer[hashtable->pool.size]; memcpy(s, name, len); hashtable->pool.size += len; @@ -416,7 +433,7 @@ static void inthash_free_name(inthash hashtable, char *name) { const size_t len = strlen(name) + 1; hashtable->pool.used -= len; if (hashtable->pool.used < hashtable->pool.size / 2) { - inthash_compact_pool(hashtable); + inthash_compact_pool(hashtable, hashtable->pool.capacity); } } |