X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=bam_aux.c;h=4fd3190a73799c6fd68257cc8c1125a017dc4860;hb=205b696ea778f5b7cfe70e5531bfe6583b5af333;hp=081f07bc367a57fe2bd139b4fd82ea73421b5d5d;hpb=f93dae0d03856955f9424e8b2aaf261304ca647e;p=samtools.git diff --git a/bam_aux.c b/bam_aux.c index 081f07b..4fd3190 100644 --- a/bam_aux.c +++ b/bam_aux.c @@ -1,8 +1,65 @@ #include #include "bam.h" #include "khash.h" -KHASH_MAP_INIT_INT(aux, uint8_t*) +typedef char *str_p; KHASH_MAP_INIT_STR(s, int) +KHASH_MAP_INIT_STR(r2l, str_p) + +void bam_aux_append(bam1_t *b, const char tag[2], char type, int len, uint8_t *data) +{ + int ori_len = b->data_len; + b->data_len += 3 + len; + b->l_aux += 3 + len; + if (b->m_data < b->data_len) { + b->m_data = b->data_len; + kroundup32(b->m_data); + b->data = (uint8_t*)realloc(b->data, b->m_data); + } + b->data[ori_len] = tag[0]; b->data[ori_len + 1] = tag[1]; + b->data[ori_len + 2] = type; + memcpy(b->data + ori_len + 3, data, len); +} + +uint8_t *bam_aux_get_core(bam1_t *b, const char tag[2]) +{ + return bam_aux_get(b, tag); +} + +#define __skip_tag(s) do { \ + int type = toupper(*(s)); \ + ++(s); \ + if (type == 'C' || type == 'A') ++(s); \ + else if (type == 'S') (s) += 2; \ + else if (type == 'I' || type == 'F') (s) += 4; \ + else if (type == 'D') (s) += 8; \ + else if (type == 'Z' || type == 'H') { while (*(s)) ++(s); ++(s); } \ + } while (0) + +uint8_t *bam_aux_get(const bam1_t *b, const char tag[2]) +{ + uint8_t *s; + int y = tag[0]<<8 | tag[1]; + s = bam1_aux(b); + while (s < b->data + b->data_len) { + int x = (int)s[0]<<8 | s[1]; + s += 2; + if (x == y) return s; + __skip_tag(s); + } + return 0; +} +// s MUST BE returned by bam_aux_get() +int bam_aux_del(bam1_t *b, uint8_t *s) +{ + uint8_t *p, *aux; + aux = bam1_aux(b); + p = s - 2; + __skip_tag(s); + memmove(p, s, b->l_aux - (s - aux)); + b->data_len -= s - p; + b->l_aux -= s - p; + return 0; +} void bam_init_header_hash(bam_header_t *header) { @@ -32,7 +89,7 @@ int32_t bam_get_tid(const bam_header_t *header, const char *seq_name) return k == kh_end(h)? -1 : kh_value(h, k); } -void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end) +int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end) { char *s, *p; int i, l, k; @@ -41,7 +98,7 @@ void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *b bam_init_header_hash(header); h = (khash_t(s)*)header->hash; - + l = strlen(str); p = s = (char*)malloc(l+1); /* squeeze out "," */ @@ -53,12 +110,12 @@ void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *b iter = kh_get(s, h, s); /* get the ref_id */ if (iter == kh_end(h)) { // name not found *ref_id = -1; free(s); - return; + return -1; } *ref_id = kh_value(h, iter); if (i == k) { /* dump the whole sequence */ *begin = 0; *end = 1<<29; free(s); - return; + return 0; } for (p = s + i + 1; i != k; ++i) if (s[i] == '-') break; *begin = atoi(p); @@ -67,94 +124,66 @@ void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *b *end = atoi(p); } else *end = 1<<29; if (*begin > 0) --*begin; - assert(*begin <= *end); free(s); -} - -void bam_aux_init(bam1_t *b) -{ - khash_t(aux) *h; - uint8_t *s; - if (b->hash == 0) { - h = kh_init(aux); - b->hash = h; - } else { - h = (khash_t(aux)*)b->hash; - kh_clear(aux, h); - } - s = bam1_aux(b); - while (s < b->data + b->data_len) { - uint32_t x = (uint32_t)s[0]<<8 | s[1]; - int ret, type; - khint_t k; - s += 2; type = toupper(*s); ++s; - k = kh_put(aux, h, x, &ret); - kh_value(h, k) = s; - if (type == 'C') ++s; - else if (type == 'S') s += 2; - else if (type == 'I') s += 4; - else if (type == 'F') s += 4; - else if (type == 'Z') { while (*s) putchar(*s++); ++s; } + if (*begin > *end) { + fprintf(stderr, "[bam_parse_region] invalid region.\n"); + return -1; } + return 0; } -void bam_aux_destroy(bam1_t *b) -{ - khash_t(aux) *h = (khash_t(aux)*)b->hash; - kh_destroy(aux, h); - b->hash = 0; -} -static uint8_t *bam_aux_get_core(bam1_t *b, const char tag[2]) -{ - uint32_t x = (uint32_t)tag[0]<<8 | tag[1]; - khint_t k; - khash_t(aux) *h; - if (b->hash == 0) bam_aux_init(b); - h = (khash_t(aux)*)b->hash; - k = kh_get(aux, h, x); - if (k == kh_end(h)) return 0; - return kh_value(h, k); -} -int32_t bam_aux_geti(bam1_t *b, const char tag[2], int *err) + +int32_t bam_aux2i(const uint8_t *s) { int type; - uint8_t *s = bam_aux_get_core(b, tag); - *err = 0; - if (s == 0) { *err = -1; return 0; } + if (s == 0) return 0; type = *s++; if (type == 'c') return (int32_t)*(int8_t*)s; else if (type == 'C') return (int32_t)*(uint8_t*)s; else if (type == 's') return (int32_t)*(int16_t*)s; else if (type == 'S') return (int32_t)*(uint16_t*)s; else if (type == 'i' || type == 'I') return *(int32_t*)s; - else { *err = -2; return 0; } + else return 0; } -float bam_aux_getf(bam1_t *b, const char tag[2], int *err) + +float bam_aux2f(const uint8_t *s) { int type; - uint8_t *s = bam_aux_get_core(b, tag); - *err = 0; type = *s++; - if (s == 0) { *err = -1; return 0; } + if (s == 0) return 0.0; if (type == 'f') return *(float*)s; - else { *err = -2; return 0; } + else return 0.0; } -char bam_aux_getc(bam1_t *b, const char tag[2], int *err) + +double bam_aux2d(const uint8_t *s) +{ + int type; + type = *s++; + if (s == 0) return 0.0; + if (type == 'd') return *(double*)s; + else return 0.0; +} + +char bam_aux2A(const uint8_t *s) { int type; - uint8_t *s = bam_aux_get_core(b, tag); - *err = 0; type = *s++; - if (s == 0) { *err = -1; return 0; } - if (type == 'c') return *(char*)s; - else { *err = -2; return 0; } + if (s == 0) return 0; + if (type == 'A') return *(char*)s; + else return 0; } -char *bam_aux_getZH(bam1_t *b, const char tag[2], int *err) + +char *bam_aux2Z(const uint8_t *s) { int type; - uint8_t *s = bam_aux_get_core(b, tag); - *err = 0; type = *s++; - if (s == 0) { *err = -1; return 0; } + if (s == 0) return 0; if (type == 'Z' || type == 'H') return (char*)s; - else { *err = -2; return 0; } + else return 0; +} + +#ifdef _WIN32 +double drand48() +{ + return (double)rand() / RAND_MAX; } +#endif