10 static void str_init(str_t* str)
14 str->s = malloc_or_die(str->size = 0);
19 static void str_free(str_t* str)
25 /* Reserve space for `size` more characters. */
26 static void str_reserve_extra(str_t* str, size_t size)
28 if (str->n + size > str->size) {
29 if (str->n + size > 2 * str->size) {
30 str->size = str->n + size;
33 str->s = realloc_or_die(str->s, str->size * sizeof(char));
38 /* Copy n characters from c to the end of str. */
39 static void str_append(str_t* str, char* c, size_t n)
41 str_reserve_extra(str, n);
42 memcpy(str->s + str->n, c, n);
44 str->s[str->n] = '\0';
50 seq_t* seq = malloc_or_die(sizeof(seq_t));
59 void seq_free(seq_t* seq)
69 static const size_t parser_buf_size = 1000000;
83 fastq_t* fastq_create(FILE* file)
85 fastq_t* f = malloc_or_die(sizeof(fastq_t));
87 f->next = f->buf = malloc_or_die(parser_buf_size);
94 void fastq_free(fastq_t* f)
102 FASTQ_STATE_ID1, /* Reading ID1. */
103 FASTQ_STATE_SEQ, /* Reading the sequence. */
104 FASTQ_STATE_ID2, /* Reading ID2. */
105 FASTQ_STATE_QUAL, /* Reading quality scores. */
106 } fastq_parser_state_t;
109 bool fastq_read(fastq_t* f, seq_t* seq)
111 seq->id1.n = seq->seq.n = seq->id2.n = seq->qual.n = 0;
112 fastq_parser_state_t state = FASTQ_STATE_ID1;
113 char* end = f->buf + f->readlen;
115 while (f->next < end) {
116 /* Consume pointless special characters prefixing IDs */
117 if ((state == FASTQ_STATE_ID1 && f->linestart && f->next[0] == '@') ||
118 (state == FASTQ_STATE_ID2 && f->linestart && f->next[0] == '+')) {
119 f->linestart = false;
124 char* u = memchr(f->next, '\n', end - f->next);
126 f->linestart = false;
129 else f->linestart = true;
132 case FASTQ_STATE_ID1:
133 str_append(&seq->id1, f->next, u - f->next);
134 if (f->linestart) state = FASTQ_STATE_SEQ;
137 case FASTQ_STATE_SEQ:
138 str_append(&seq->seq, f->next, u - f->next);
139 if (f->linestart) state = FASTQ_STATE_ID2;
142 case FASTQ_STATE_ID2:
143 str_append(&seq->id2, f->next, u - f->next);
144 if (f->linestart) state = FASTQ_STATE_QUAL;
147 case FASTQ_STATE_QUAL:
148 str_append(&seq->qual, f->next, u - f->next);
159 /* Try to read more. */
160 f->readlen = fread(f->buf, 1, parser_buf_size, f->file);
162 end = f->buf + f->readlen;
163 } while (f->readlen);
169 void fastq_rewind(fastq_t* f)
177 void fastq_print(FILE* fout, const seq_t* seq)
179 fprintf(fout, "@%s\n%s\n+%s\n%s\n",