btllib
 All Classes Namespaces Functions Variables
seq_reader_fasta_module.hpp
1 #ifndef BTLLIB_SEQ_READER_FASTA_MODULE_HPP
2 #define BTLLIB_SEQ_READER_FASTA_MODULE_HPP
3 
4 #include "btllib/status.hpp"
5 
6 #include <cstdlib>
7 
8 namespace btllib {
9 
11 class SeqReaderFastaModule
12 {
13 
14 private:
15  friend class SeqReader;
16 
17  enum class Stage
18  {
19  HEADER,
20  SEQ
21  };
22 
23  Stage stage = Stage::HEADER;
24 
25  static bool buffer_valid(const char* buffer, size_t size);
26  template<typename ReaderType, typename RecordType>
27  bool read_buffer(ReaderType& reader, RecordType& record);
28  template<typename ReaderType, typename RecordType>
29  bool read_transition(ReaderType& reader, RecordType& record);
30  template<typename ReaderType, typename RecordType>
31  bool read_file(ReaderType& reader, RecordType& record);
32 };
33 
34 template<typename ReaderType, typename RecordType>
35 inline bool
36 SeqReaderFastaModule::read_buffer(ReaderType& reader, RecordType& record)
37 {
38  record.header.clear();
39  record.seq.clear();
40  record.qual.clear();
41  if (reader.buffer.start < reader.buffer.end) {
42  switch (stage) {
43  case Stage::HEADER: {
44  if (!reader.readline_buffer_append(record.header)) {
45  return false;
46  }
47  stage = Stage::SEQ;
48  }
49  // fall through
50  case Stage::SEQ: {
51  if (!reader.readline_buffer_append(record.seq)) {
52  return false;
53  }
54  stage = Stage::HEADER;
55  return true;
56  }
57  default: {
58  log_error("SeqReader has entered an invalid state.");
59  std::exit(EXIT_FAILURE); // NOLINT(concurrency-mt-unsafe)
60  }
61  }
62  }
63  return false;
64 }
65 
66 template<typename ReaderType, typename RecordType>
67 inline bool
68 SeqReaderFastaModule::read_transition(ReaderType& reader, RecordType& record)
69 {
70  if (std::ferror(reader.source) == 0 && std::feof(reader.source) == 0) {
71  const auto p = std::fgetc(reader.source);
72  if (p != EOF) {
73  const auto ret = std::ungetc(p, reader.source);
74  check_error(ret == EOF, "SeqReaderFastaModule: ungetc failed.");
75  switch (stage) {
76  case Stage::HEADER: {
77  reader.readline_file_append(record.header, reader.source);
78  stage = Stage::SEQ;
79  }
80  // fall through
81  case Stage::SEQ: {
82  reader.readline_file_append(record.seq, reader.source);
83  stage = Stage::HEADER;
84  return true;
85  }
86  default: {
87  log_error("SeqReader has entered an invalid state.");
88  std::exit(EXIT_FAILURE); // NOLINT(concurrency-mt-unsafe)
89  }
90  }
91  }
92  }
93  return false;
94 }
95 
96 template<typename ReaderType, typename RecordType>
97 inline bool
98 SeqReaderFastaModule::read_file(ReaderType& reader, RecordType& record)
99 {
100  if (!reader.file_at_end(reader.source)) {
101  reader.readline_file(record.header, reader.source);
102  reader.readline_file(record.seq, reader.source);
103  return true;
104  }
105  return false;
106 }
108 
109 } // namespace btllib
110 
111 #endif
void check_error(bool condition, const std::string &msg)
void log_error(const std::string &msg)