diff --git a/khash.h b/khash.h index e44f328..8942158 100644 --- a/khash.h +++ b/khash.h @@ -169,6 +169,7 @@ typedef khint_t khiter_t; #define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) #define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) #define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) +#define __ac_fw(item, fp) (fwrite(&(item), 1, sizeof(item), fp)) #define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) @@ -352,7 +353,39 @@ static const double __ac_HASH_UPPER = 0.77; __ac_set_isdel_true(h->flags, x); \ --h->size; \ } \ - } + } \ + SCOPE void kh_write_##name(kh_##name##_t *map, const char *path) { \ + FILE *fp = fopen(path, "wb"); \ + if(fp == NULL) { \ + fprintf(stderr, "[%s] Could not open file %s.\n", __func__, path);\ + exit(EXIT_FAILURE); \ + } \ + __ac_fw(map->n_buckets, fp); \ + __ac_fw(map->n_occupied, fp); \ + __ac_fw(map->size, fp); \ + __ac_fw(map->upper_bound, fp); \ + fwrite(map->flags, __ac_fsize(map->n_buckets), sizeof(khint32_t), fp);\ + fwrite(map->keys, map->n_buckets, sizeof(*map->keys), fp); \ + if(kh_is_map) fwrite(map->vals, map->n_buckets, sizeof(*map->vals), fp); \ + fclose(fp); \ + } \ + SCOPE kh_##name##_t *khash_load_##name(const char *path) \ + { \ + kh_##name##_t *ret = (kh_##name##_t *)calloc(1, sizeof(kh_##name##_t)); \ + FILE *fp = fopen(path, "rb"); \ + fread(&ret->n_buckets, 1, sizeof(ret->n_buckets), fp); \ + fread(&ret->n_occupied, 1, sizeof(ret->n_occupied), fp); \ + fread(&ret->size, 1, sizeof(ret->size), fp); \ + fread(&ret->upper_bound, 1, sizeof(ret->upper_bound), fp); \ + ret->flags = (khint32_t *)malloc(sizeof(*ret->flags) * __ac_fsize(ret->n_buckets));\ + ret->keys = (khkey_t *)malloc(sizeof(khkey_t) * ret->n_buckets); \ + ret->vals = kh_is_map ? (khval_t *)malloc(sizeof(khval_t) * ret->n_buckets) : 0; \ + fread(ret->flags, __ac_fsize(ret->n_buckets), sizeof(*ret->flags), fp);\ + fread(ret->keys, 1, ret->n_buckets * sizeof(*ret->keys), fp); \ + if(kh_is_map) fread(ret->vals, 1, ret->n_buckets * sizeof(*ret->vals), fp); \ + fclose(fp); \ + return ret; \ + } #define KHASH_DECLARE(name, khkey_t, khval_t) \ __KHASH_TYPE(name, khkey_t, khval_t) \ @@ -491,6 +524,21 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) #define kh_del(name, h, k) kh_del_##name(h, k) /*! @function + @abstract Write a hash map to disk. + @param h Pointer to the hash table [khash_t(name)*] + @param path Path to which to write. [const char *] + */ +#define kh_write(name, h, path) kh_write_##name(h, path) + +/*! @function + @abstract Load a hash table from disk + @param name Name of the hash table [symbol] + @param path Path to file from which to load [const char *] + */ + +#define kh_load(name, path) khash_load_##name(path) + +/*! @function @abstract Test whether a bucket contains data. @param h Pointer to the hash table [khash_t(name)*] @param x Iterator to the bucket [khint_t] diff --git a/kstring.c b/kstring.c index 253d281..5adbe4f 100644 --- a/kstring.c +++ b/kstring.c @@ -12,7 +12,7 @@ int kvsprintf(kstring_t *s, const char *fmt, va_list ap) va_copy(args, ap); l = vsnprintf(s->s + s->l, s->m - s->l, fmt, args); // This line does not work with glibc 2.0. See `man snprintf'. va_end(args); - if (l + 1 > s->m - s->l) { + if ((unsigned)(l + 1) > s->m - s->l) { s->m = s->l + l + 2; kroundup32(s->m); s->s = (char*)realloc(s->s, s->m); diff --git a/kstring.h b/kstring.h index f13fcd9..89e46d3 100644 --- a/kstring.h +++ b/kstring.h @@ -220,6 +220,29 @@ static inline int kputw(int c, kstring_t *s) return 0; } + +static inline int kputw_(int c, kstring_t *s) +{ + char buf[16]; + int i, l = 0; + unsigned int x = c; + if (c < 0) x = -x; + do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0); + if (c < 0) buf[l++] = '-'; + if (s->l + l + 1 >= s->m) { + char *tmp; + s->m = s->l + l + 2; + kroundup32(s->m); + if ((tmp = (char*)realloc(s->s, s->m))) + s->s = tmp; + else + return EOF; + } + for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i]; + return 0; +} + + static inline int kputuw(unsigned c, kstring_t *s) { char buf[16]; @@ -241,6 +264,30 @@ static inline int kputuw(unsigned c, kstring_t *s) return 0; } +#ifndef HAS_KPUTUW__ +#define HAS_KPUTUW__ +static inline int kputuw_(unsigned c, kstring_t *s) +{ + char buf[16]; + int l, i; + unsigned x; + if (c == 0) return kputc('0', s); + for (l = 0, x = c; x > 0; x /= 10) buf[l++] = x%10 + '0'; + if (s->l + l + 1 >= s->m) { + char *tmp; + s->m = s->l + l + 2; + kroundup32(s->m); + if ((tmp = (char*)realloc(s->s, s->m))) + s->s = tmp; + else + return EOF; + } + for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i]; + return 0; +} +#endif + + static inline int kputl(long c, kstring_t *s) { char buf[32]; @@ -263,6 +310,28 @@ static inline int kputl(long c, kstring_t *s) return 0; } + +static inline int kputl_(long c, kstring_t *s) +{ + char buf[32]; + int i, l = 0; + unsigned long x = c; + if (c < 0) x = -x; + do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0); + if (c < 0) buf[l++] = '-'; + if (s->l + l + 1 >= s->m) { + char *tmp; + s->m = s->l + l + 2; + kroundup32(s->m); + if ((tmp = (char*)realloc(s->s, s->m))) + s->s = tmp; + else + return EOF; + } + for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i]; + return 0; +} + /* * Returns 's' split by delimiter, with *n being the number of components; * NULL on failue.