|
18 | 18 | #include <string> |
19 | 19 | #include <stdexcept> |
20 | 20 | #include <fstream> |
| 21 | +#include <charconv> |
21 | 22 |
|
22 | 23 | #include "Epiread.hpp" |
23 | 24 |
|
@@ -76,3 +77,42 @@ validate_epiread_file(const string &filename) { |
76 | 77 | } |
77 | 78 | return true; |
78 | 79 | } |
| 80 | + |
| 81 | +epiread::epiread(const string &line) { |
| 82 | + constexpr auto is_sep = [](const char x) { return x == ' ' || x == '\t'; }; |
| 83 | + constexpr auto not_sep = [](const char x) { return x != ' ' && x != '\t'; }; |
| 84 | + |
| 85 | + using std::find_if; |
| 86 | + using std::from_chars; |
| 87 | + using std::distance; |
| 88 | + |
| 89 | + bool failed = false; |
| 90 | + |
| 91 | + const auto c = line.data(); |
| 92 | + const auto c_end = c + line.size(); |
| 93 | + |
| 94 | + auto field_s = c; |
| 95 | + auto field_e = find_if(field_s + 1, c_end, is_sep); |
| 96 | + if (field_e == c_end) failed = true; |
| 97 | + |
| 98 | + chr = string{field_s, static_cast<uint32_t>(distance(field_s, field_e))}; |
| 99 | + |
| 100 | + field_s = find_if(field_e + 1, c_end, not_sep); |
| 101 | + field_e = find_if(field_s + 1, c_end, is_sep); |
| 102 | + failed = failed || (field_e == c_end); |
| 103 | + |
| 104 | + const auto [ptr, ec] = from_chars(field_s, field_e, pos); |
| 105 | + failed = failed || (ptr == field_s); |
| 106 | + |
| 107 | + field_s = find_if(field_e + 1, c_end, not_sep); |
| 108 | + field_e = find_if(field_s + 1, c_end, is_sep); |
| 109 | + failed = failed || (field_e != c_end); |
| 110 | + |
| 111 | + seq = string{field_s, static_cast<uint32_t>(distance(field_s, field_e))}; |
| 112 | + |
| 113 | + if (failed) { |
| 114 | + throw std::runtime_error("bad epiread line: " + line); |
| 115 | + // ADS: the value below would work for a flag |
| 116 | + // pos = std::numeric_limits<decltype(pos)>::max(); |
| 117 | + } |
| 118 | +} |
0 commit comments