btllib
seq_reader_fastq_module.hpp
1#ifndef BTLLIB_SEQ_READER_FASTQ_MODULE_HPP
2#define BTLLIB_SEQ_READER_FASTQ_MODULE_HPP
3
4#include "btllib/cstring.hpp"
5#include "btllib/status.hpp"
6
7#include <cstdlib>
8
9namespace btllib {
10
12class SeqReaderFastqModule
13{
14
15private:
16 friend class SeqReader;
17
18 enum class Stage
19 {
20 HEADER,
21 SEQ,
22 SEP,
23 QUAL
24 };
25
26 Stage stage = Stage::HEADER;
27 CString tmp;
28
29 static bool buffer_valid(const char* buffer, size_t size);
30 template<typename ReaderType, typename RecordType>
31 bool read_buffer(ReaderType& reader, RecordType& record);
32 template<typename ReaderType, typename RecordType>
33 bool read_transition(ReaderType& reader, RecordType& record);
34 template<typename ReaderType, typename RecordType>
35 bool read_file(ReaderType& reader, RecordType& record);
36};
37
38template<typename ReaderType, typename RecordType>
39inline bool
40SeqReaderFastqModule::read_buffer(ReaderType& reader, RecordType& record)
41{
42 record.header.clear();
43 record.seq.clear();
44 record.qual.clear();
45 if (reader.buffer.start < reader.buffer.end) {
46 switch (stage) {
47 case Stage::HEADER: {
48 if (!reader.readline_buffer_append(record.header)) {
49 return false;
50 }
51 stage = Stage::SEQ;
52 }
53 // fall through
54 case Stage::SEQ: {
55 if (!reader.readline_buffer_append(record.seq)) {
56 return false;
57 }
58 stage = Stage::SEP;
59 }
60 // fall through
61 case Stage::SEP: {
62 if (!reader.readline_buffer_append(tmp)) {
63 return false;
64 }
65 stage = Stage::QUAL;
66 tmp.clear();
67 }
68 // fall through
69 case Stage::QUAL: {
70 if (!reader.readline_buffer_append(record.qual)) {
71 return false;
72 }
73 stage = Stage::HEADER;
74 return true;
75 }
76 default: {
77 log_error("SeqReader has entered an invalid state.");
78 std::exit(EXIT_FAILURE); // NOLINT(concurrency-mt-unsafe)
79 }
80 }
81 }
82 return false;
83}
84
85template<typename ReaderType, typename RecordType>
86inline bool
87SeqReaderFastqModule::read_transition(ReaderType& reader, RecordType& record)
88{
89 if (std::ferror(reader.source) == 0 && std::feof(reader.source) == 0) {
90 const auto p = std::fgetc(reader.source);
91 if (p != EOF) {
92 std::ungetc(p, reader.source);
93 switch (stage) {
94 case Stage::HEADER: {
95 reader.readline_file_append(record.header, reader.source);
96 stage = Stage::SEQ;
97 }
98 // fall through
99 case Stage::SEQ: {
100 reader.readline_file_append(record.seq, reader.source);
101 stage = Stage::SEP;
102 }
103 // fall through
104 case Stage::SEP: {
105 reader.readline_file_append(tmp, reader.source);
106 stage = Stage::QUAL;
107 tmp.clear();
108 }
109 // fall through
110 case Stage::QUAL: {
111 reader.readline_file_append(record.qual, reader.source);
112 stage = Stage::HEADER;
113 return true;
114 }
115 default: {
116 log_error("SeqReader has entered an invalid state.");
117 std::exit(EXIT_FAILURE); // NOLINT(concurrency-mt-unsafe)
118 }
119 }
120 }
121 }
122 return false;
123}
124
125template<typename ReaderType, typename RecordType>
126inline bool
127SeqReaderFastqModule::read_file(ReaderType& reader, RecordType& record)
128{
129 if (!reader.file_at_end(reader.source)) {
130 reader.readline_file(record.header, reader.source);
131 reader.readline_file(record.seq, reader.source);
132 reader.readline_file(tmp, reader.source);
133 reader.readline_file(record.qual, reader.source);
134 return true;
135 }
136 return false;
137}
139
140} // namespace btllib
141
142#endif
Definition: bloom_filter.hpp:16
void log_error(const std::string &msg)