diff options
author | Xavier Roche <xroche@users.noreply.github.com> | 2013-07-14 07:58:16 +0000 |
---|---|---|
committer | Xavier Roche <xroche@users.noreply.github.com> | 2013-07-14 07:58:16 +0000 |
commit | 496a08ec7d0d4d83dffab19667456c6e186c9991 (patch) | |
tree | 7485520b16fbc3489ed7cb1f1d1251601d3e33b5 /src | |
parent | 7d8c7064c2d32dee6f651a11f2685238f40932a5 (diff) |
handle empty strings as a specific case in the strings pool, so that we can consider them as sign of duplicate release
Diffstat (limited to 'src')
-rw-r--r-- | src/htsinthash.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/htsinthash.c b/src/htsinthash.c index 5777435..a25bd85 100644 --- a/src/htsinthash.c +++ b/src/htsinthash.c @@ -483,17 +483,31 @@ 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; + /* the pool does not allow empty strings for safety purpose ; handhe that + (keys are being emptied when free'd to detect duplicate free) */ + if (len == 1) { + assert(the_empty_string[0] == '\0'); + return the_empty_string; + } + + /* expand pool capacity */ + assert(hashtable->pool.size <= hashtable->pool.capacity); if (hashtable->pool.capacity - hashtable->pool.size < len) { size_t capacity; for(capacity = MIN_POOL_CAPACITY ; capacity < hashtable->pool.size + len ; capacity <<= 1) ; + assert(hashtable->pool.size < capacity); inthash_realloc_pool(hashtable, capacity); } + /* copy */ assert(len + hashtable->pool.size <= hashtable->pool.capacity); s = &hashtable->pool.buffer[hashtable->pool.size]; memcpy(s, name, len); @@ -514,12 +528,25 @@ static HTS_INLINE char* inthash_dup_name(inthash hashtable, const char *name) { note: pointer must have been kicked from the pool first */ static void inthash_free_key_internal(inthash hashtable, char *name) { const size_t len = strlen(name) + 1; + + /* see inthash_dup_name_internal() handling */ + if (len == 1 && name == the_empty_string) { + assert(the_empty_string[0] == '\0'); + return ; + } + + assert(*name != '\0' || !"duplicate or bad string pool release"); hashtable->pool.used -= len; + *name = '\0'; /* the string is now invalidated */ + + /* compact the pool is too many holes */ if (hashtable->pool.used < hashtable->pool.size / 2) { size_t capacity = hashtable->pool.capacity; + /* compact and shrink */ if (hashtable->pool.used < capacity / 4) { capacity /= 2; } + assert(hashtable->pool.used < capacity); inthash_compact_pool(hashtable, capacity); } } |