7 bam_header_t *bam_header_dup(const bam_header_t *h0)
11 h = bam_header_init();
14 h->text = (char*)calloc(h->l_text + 1, 1);
15 memcpy(h->text, h0->text, h->l_text);
16 h->target_len = (uint32_t*)calloc(h->n_targets, 4);
17 h->target_name = (char**)calloc(h->n_targets, sizeof(void*));
18 for (i = 0; i < h->n_targets; ++i) {
19 h->target_len[i] = h0->target_len[i];
20 h->target_name[i] = strdup(h0->target_name[i]);
25 bam_header_t *bam_header_parse(const char *text)
32 if (i < 3) return 0; // headerless
33 h = bam_header_init();
35 h->text = strdup(text);
37 while ((s = strstr(s, "@SQ")) != 0) {
41 h->target_len = (uint32_t*)calloc(h->n_targets, 4);
42 h->target_name = (char**)calloc(h->n_targets, sizeof(void*));
45 while ((s = strstr(s, "@SQ")) != 0) {
48 if ((p = strstr(s, "SN:")) != 0) {
50 for (p = q; *p && *p != '\t'; ++p);
51 h->target_name[i] = (char*)calloc(p - q + 1, 1);
52 strncpy(h->target_name[i], q, p - q);
53 } else goto header_err_ret;
55 if ((p = strstr(s, "LN:")) != 0) h->target_len[i] = strtol(p + 3, 0, 10);
56 else goto header_err_ret;
61 if (h->n_targets == 0) {
62 bam_header_destroy(h);
67 fprintf(stderr, "[bam_header_parse] missing SN tag in a @SQ line.\n");
68 bam_header_destroy(h);
72 samfile_t *samopen(const char *fn, const char *mode, const void *aux)
75 fp = (samfile_t*)calloc(1, sizeof(samfile_t));
77 const char *fn_list = (const char*)aux;
78 fp->type |= TYPE_READ;
79 if (mode[1] == 'b') { // binary
81 fp->x.bam = strcmp(fn, "-")? bam_open(fn, "r") : bam_dopen(fileno(stdin), "r");
82 if (fp->x.bam == 0) goto open_err_ret;
83 fp->header = bam_header_read(fp->x.bam);
85 fp->x.tamr = sam_open(fn);
86 if (fp->x.tamr == 0) goto open_err_ret;
87 fp->header = sam_header_read2(fn_list);
89 } else if (mode[0] == 'w') {
90 fp->header = bam_header_dup((const bam_header_t*)aux);
91 if (mode[1] == 'b') { // binary
93 fp->x.bam = strcmp(fn, "-")? bam_open(fn, "w") : bam_dopen(fileno(stdout), "w");
94 if (fp->x.bam == 0) goto open_err_ret;
95 bam_header_write(fp->x.bam, fp->header);
98 bam_header_t *alt = 0;
99 alt = bam_header_parse(fp->header->text);
100 fp->x.tamw = strcmp(fn, "-")? fopen(fn, "w") : stdout;
101 if (fp->x.tamr == 0) goto open_err_ret;
103 if (alt->n_targets != fp->header->n_targets)
104 fprintf(stderr, "[samopen] inconsistent number of target sequences.\n");
105 bam_header_destroy(alt);
106 fwrite(fp->header->text, 1, fp->header->l_text, fp->x.tamw);
108 if (strstr(mode, "h")) // print header
109 for (i = 0; i < fp->header->n_targets; ++i)
110 fprintf(fp->x.tamw, "@SQ\tSN:%s\tLN:%d\n", fp->header->target_name[i], fp->header->target_len[i]);
120 void samclose(samfile_t *fp)
123 if (fp->header) bam_header_destroy(fp->header);
124 if (fp->type & TYPE_BAM) bam_close(fp->x.bam);
125 else if (fp->type & TYPE_READ) sam_close(fp->x.tamr);
126 else fclose(fp->x.tamw);
130 int samread(samfile_t *fp, bam1_t *b)
132 if (fp == 0 || !(fp->type & TYPE_READ)) return -1; // not open for reading
133 if (fp->type & TYPE_BAM) return bam_read1(fp->x.bam, b);
134 else return sam_read1(fp->x.tamr, fp->header, b);
137 int samwrite(samfile_t *fp, const bam1_t *b)
139 if (fp == 0 || (fp->type & TYPE_READ)) return -1; // not open for writing
140 if (fp->type & TYPE_BAM) return bam_write1(fp->x.bam, b);
142 char *s = bam_format1(fp->header, b);
144 fputs(s, fp->x.tamw); fputc('\n', fp->x.tamw);
150 int sampileup(samfile_t *fp, int mask, bam_pileup_f func, void *func_data)
156 buf = bam_plbuf_init(func, func_data);
157 bam_plbuf_set_mask(buf, mask);
158 while ((ret = samread(fp, b)) >= 0)
159 bam_plbuf_push(b, buf);
160 bam_plbuf_push(0, buf);
161 bam_plbuf_destroy(buf);