btllib
 All Classes Namespaces Functions Variables
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 
9 namespace btllib {
10 
12 class SeqReaderFastqModule
13 {
14 
15 private:
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 
38 template<typename ReaderType, typename RecordType>
39 inline bool
40 SeqReaderFastqModule::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 
85 template<typename ReaderType, typename RecordType>
86 inline bool
87 SeqReaderFastqModule::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  const auto ret = std::ungetc(p, reader.source);
93  check_error(ret == EOF, "SeqReaderFastqModule: ungetc failed.");
94  switch (stage) {
95  case Stage::HEADER: {
96  reader.readline_file_append(record.header, reader.source);
97  stage = Stage::SEQ;
98  }
99  // fall through
100  case Stage::SEQ: {
101  reader.readline_file_append(record.seq, reader.source);
102  stage = Stage::SEP;
103  }
104  // fall through
105  case Stage::SEP: {
106  reader.readline_file_append(tmp, reader.source);
107  stage = Stage::QUAL;
108  tmp.clear();
109  }
110  // fall through
111  case Stage::QUAL: {
112  reader.readline_file_append(record.qual, reader.source);
113  stage = Stage::HEADER;
114  return true;
115  }
116  default: {
117  log_error("SeqReader has entered an invalid state.");
118  std::exit(EXIT_FAILURE); // NOLINT(concurrency-mt-unsafe)
119  }
120  }
121  }
122  }
123  return false;
124 }
125 
126 template<typename ReaderType, typename RecordType>
127 inline bool
128 SeqReaderFastqModule::read_file(ReaderType& reader, RecordType& record)
129 {
130  if (!reader.file_at_end(reader.source)) {
131  reader.readline_file(record.header, reader.source);
132  reader.readline_file(record.seq, reader.source);
133  reader.readline_file(tmp, reader.source);
134  reader.readline_file(record.qual, reader.source);
135  return true;
136  }
137  return false;
138 }
140 
141 } // namespace btllib
142 
143 #endif
void check_error(bool condition, const std::string &msg)
void log_error(const std::string &msg)