1#ifndef BTLLIB_SEQ_READER_MULTILINE_FASTQ_MODULE_HPP
2#define BTLLIB_SEQ_READER_MULTILINE_FASTQ_MODULE_HPP
4#include "btllib/cstring.hpp"
5#include "btllib/status.hpp"
12class SeqReaderMultilineFastqModule
16 friend class SeqReader;
27 Stage stage = Stage::HEADER;
30 static bool buffer_valid(
const char* buffer,
size_t size);
31 template<
typename ReaderType,
typename RecordType>
32 bool read_buffer(ReaderType& reader, RecordType& record);
33 template<
typename ReaderType,
typename RecordType>
34 bool read_transition(ReaderType& reader, RecordType& record);
35 template<
typename ReaderType,
typename RecordType>
36 bool read_file(ReaderType& reader, RecordType& record);
39template<
typename ReaderType,
typename RecordType>
41SeqReaderMultilineFastqModule::read_buffer(ReaderType& reader,
44 record.header.clear();
47 if (reader.buffer.start < reader.buffer.end) {
52 if (!reader.readline_buffer_append(record.header)) {
59 if (!reader.readline_buffer_append(record.seq)) {
63 stage = Stage::TRANSITION;
66 case Stage::TRANSITION: {
67 c = reader.getc_buffer();
71 reader.ungetc_buffer(c);
80 if (!reader.readline_buffer_append(tmp)) {
88 if (!reader.readline_buffer_append(record.qual)) {
92 if (record.qual.size() == record.seq.size()) {
93 stage = Stage::HEADER;
97 "SeqReader: Multiline FASTQ reader: Quality string is "
98 "longer than sequence string.");
102 log_error(
"SeqReader has entered an invalid state.");
103 std::exit(EXIT_FAILURE);
111template<
typename ReaderType,
typename RecordType>
113SeqReaderMultilineFastqModule::read_transition(ReaderType& reader,
116 if (std::ferror(reader.source) == 0 && std::feof(reader.source) == 0) {
117 const auto p = std::fgetc(reader.source);
119 const auto ret = std::ungetc(p, reader.source);
120 check_error(ret == EOF,
"SeqReaderMultilineFastqModule: ungetc failed.");
124 case Stage::HEADER: {
125 reader.readline_file_append(record.header, reader.source);
130 reader.readline_file_append(record.seq, reader.source);
132 stage = Stage::TRANSITION;
135 case Stage::TRANSITION: {
136 c = std::fgetc(reader.source);
140 const auto ret = std::ungetc(c, reader.source);
142 "SeqReaderMultilineFastqModule: ungetc failed.");
151 reader.readline_file_append(tmp, reader.source);
157 reader.readline_file_append(record.qual, reader.source);
159 if (record.qual.size() == record.seq.size()) {
160 stage = Stage::HEADER;
163 check_error(record.qual.size() > record.seq.size(),
164 "SeqReader: Multiline FASTQ reader: Quality string is "
165 "longer than sequence string.");
169 log_error(
"SeqReader has entered an invalid state.");
170 std::exit(EXIT_FAILURE);
179template<
typename ReaderType,
typename RecordType>
181SeqReaderMultilineFastqModule::read_file(ReaderType& reader, RecordType& record)
183 if (!reader.file_at_end(reader.source)) {
184 reader.readline_file(record.header, reader.source);
186 reader.readline_file(record.seq, reader.source);
189 c = std::fgetc(reader.source);
191 "SeqReader: Multiline FASTQ reader: Unexpected end.");
192 const auto ret = std::ungetc(c, reader.source);
193 check_error(ret == EOF,
"SeqReaderMultilineFastqModule: ungetc failed.");
195 reader.readline_file(tmp, reader.source);
196 reader.readline_file(record.qual, reader.source);
199 while (record.qual.size() < record.seq.size()) {
200 prevlen = record.qual.size();
201 reader.readline_file_append(record.qual, reader.source);
203 "SeqReader: Multiline FASTQ reader: Failed to read the "
207 check_error(record.qual.size() > record.seq.size(),
208 "SeqReader: Multiline FASTQ reader: Quality string is "
209 "longer than sequence string.");
212 reader.readline_file_append(record.seq, reader.source);
void check_error(bool condition, const std::string &msg)
void rtrim(std::string &s)
void log_error(const std::string &msg)