btllib
Loading...
Searching...
No Matches
seq_reader_multiline_fasta_module.hpp
1#ifndef BTLLIB_SEQ_READER_MULTILINE_FASTA_MODULE_HPP
2#define BTLLIB_SEQ_READER_MULTILINE_FASTA_MODULE_HPP
3
4#include "btllib/cstring.hpp"
5#include "btllib/status.hpp"
6
7#include <cstdlib>
8
9namespace btllib {
10
12class SeqReaderMultilineFastaModule
13{
14
15private:
16 friend class SeqReader;
17
18 enum class Stage
19 {
20 HEADER,
21 SEQ,
22 TRANSITION,
23 };
24
25 Stage stage = Stage::HEADER;
26
27 static bool buffer_valid(const char* buffer, size_t size);
28 template<typename ReaderType, typename RecordType>
29 bool read_buffer(ReaderType& reader, RecordType& record);
30 template<typename ReaderType, typename RecordType>
31 bool read_transition(ReaderType& reader, RecordType& record);
32 template<typename ReaderType, typename RecordType>
33 bool read_file(ReaderType& reader, RecordType& record);
34};
35
36template<typename ReaderType, typename RecordType>
37inline bool
38SeqReaderMultilineFastaModule::read_buffer(ReaderType& reader,
39 RecordType& record)
40{
41 record.header.clear();
42 record.seq.clear();
43 record.qual.clear();
44 if (reader.buffer.start < reader.buffer.end) {
45 int c;
46 for (;;) {
47 switch (stage) {
48 case Stage::HEADER: {
49 if (!reader.readline_buffer_append(record.header)) {
50 return false;
51 }
52 stage = Stage::SEQ;
53 }
54 // fall through
55 case Stage::SEQ: {
56 if (!reader.readline_buffer_append(record.seq)) {
57 return false;
58 }
59 rtrim(record.seq);
60 stage = Stage::TRANSITION;
61 }
62 // fall through
63 case Stage::TRANSITION: {
64 c = reader.getc_buffer();
65 if (c == EOF) {
66 return false;
67 }
68 reader.ungetc_buffer(c);
69 if (c == '>') {
70 stage = Stage::HEADER;
71 return true;
72 }
73 stage = Stage::SEQ;
74 break;
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 }
83 return false;
84}
85
86template<typename ReaderType, typename RecordType>
87inline bool
88SeqReaderMultilineFastaModule::read_transition(ReaderType& reader,
89 RecordType& record)
90{
91 if (std::ferror(reader.source) == 0 && std::feof(reader.source) == 0) {
92 const auto p = std::fgetc(reader.source);
93 if (p != EOF) {
94 const auto ret = std::ungetc(p, reader.source);
95 check_error(ret == EOF, "SeqReaderMultilineFastaModule: ungetc failed.");
96 int c;
97 for (;;) {
98 switch (stage) {
99 case Stage::HEADER: {
100 reader.readline_file_append(record.header, reader.source);
101 stage = Stage::SEQ;
102 }
103 // fall through
104 case Stage::SEQ: {
105 reader.readline_file_append(record.seq, reader.source);
106 rtrim(record.seq);
107 stage = Stage::TRANSITION;
108 }
109 // fall through
110 case Stage::TRANSITION: {
111 c = std::fgetc(reader.source);
112 if (c == EOF) {
113 return false;
114 }
115 const auto ret = std::ungetc(c, reader.source);
116 check_error(ret == EOF,
117 "SeqReaderMultilineFastaModule: ungetc failed.");
118 if (c == '>') {
119 stage = Stage::HEADER;
120 return true;
121 }
122 stage = Stage::SEQ;
123 break;
124 }
125 default: {
126 log_error("SeqReader has entered an invalid state.");
127 std::exit(EXIT_FAILURE); // NOLINT(concurrency-mt-unsafe)
128 }
129 }
130 }
131 }
132 }
133 return false;
134}
135
136template<typename ReaderType, typename RecordType>
137inline bool
138SeqReaderMultilineFastaModule::read_file(ReaderType& reader, RecordType& record)
139{
140 if (!reader.file_at_end(reader.source)) {
141 reader.readline_file(record.header, reader.source);
142 int c;
143 reader.readline_file(record.seq, reader.source);
144 rtrim(record.seq);
145 for (;;) {
146 c = std::fgetc(reader.source);
147 if (c == EOF) {
148 return true;
149 }
150 const auto ret = std::ungetc(c, reader.source);
151 check_error(ret == EOF, "SeqReaderMultilineFastaModule: ungetc failed.");
152 if (c == '>') {
153 return true;
154 }
155 reader.readline_file_append(record.seq, reader.source);
156 rtrim(record.seq);
157 }
158 }
159 return false;
160}
162
163} // namespace btllib
164
165#endif
Definition aahash.hpp:12
void check_error(bool condition, const std::string &msg)
void rtrim(std::string &s)
void log_error(const std::string &msg)