btllib
seq_reader_sam_module.hpp
1#ifndef BTLLIB_SEQ_READER_SAM_MODULE_HPP
2#define BTLLIB_SEQ_READER_SAM_MODULE_HPP
3
4#include "btllib/cstring.hpp"
5#include "btllib/process_pipeline.hpp"
6#include "btllib/seq.hpp"
7#include "btllib/status.hpp"
8
9#include <cstdio>
10#include <memory>
11#include <thread>
12
13namespace btllib {
14
16class SeqReaderSamModule
17{
18
19private:
20 friend class SeqReader;
21
22 enum class Stage
23 {
24 HEADER,
25 ALIGNMENTS
26 };
27
28 std::unique_ptr<ProcessPipeline> samtools_process;
29 std::unique_ptr<std::thread> loader_thread;
30 CString tmp;
31 static const size_t LOADER_BLOCK_SIZE = 4096;
32
33 static bool buffer_valid(const char* buffer, size_t size);
34 template<typename ReaderType, typename RecordType>
35 bool read_buffer(ReaderType& reader, RecordType& record);
36 template<typename ReaderType, typename RecordType>
37 bool read_transition(ReaderType& reader, RecordType& record);
38 template<typename ReaderType, typename RecordType>
39 bool read_file(ReaderType& reader, RecordType& record);
40};
41
42template<typename ReaderType, typename RecordType>
43inline bool
44SeqReaderSamModule::read_buffer(ReaderType& reader, RecordType& record)
45{
46 (void)reader;
47 (void)record;
48 {
49 ProcessPipeline version_test("samtools --version 2>/dev/stdout | head -n2");
50 char* line = nullptr;
51 size_t n = 0;
52 std::string version = "\n";
53
54 check_error(getline(&line, &n, version_test.out) < 2,
55 "Failed to get samtools version.");
56 version += line;
57
58 line = nullptr;
59 check_error(getline(&line, &n, version_test.out) < 2,
60 "Failed to get samtools version.");
61 version += line;
62 version.pop_back();
63
64 log_info(version);
65 }
66 samtools_process =
67 std::unique_ptr<ProcessPipeline>(new ProcessPipeline("samtools fastq"));
68 loader_thread =
69 std::unique_ptr<std::thread>(new std::thread([this, &reader]() {
70 check_error(fwrite(reader.buffer.data.data() + reader.buffer.start,
71 1,
72 reader.buffer.end - reader.buffer.start,
73 samtools_process->in) !=
74 reader.buffer.end - reader.buffer.start,
75 "SeqReader SAM module: fwrite failed.");
76 reader.buffer.start = reader.buffer.end;
77 if (std::ferror(reader.source) == 0 && std::feof(reader.source) == 0) {
78 const auto p = std::fgetc(reader.source);
79 if (p != EOF) {
80 std::ungetc(p, reader.source);
81 while (std::ferror(reader.source) == 0 &&
82 std::feof(reader.source) == 0) {
83 const size_t bufsize = LOADER_BLOCK_SIZE;
84 char buf[bufsize];
85 size_t bytes_read = fread(buf, 1, bufsize, reader.source);
86 check_error(fwrite(buf, 1, bytes_read, samtools_process->in) !=
87 bytes_read,
88 "SeqReader SAM module: fwrite failed.");
89 }
90 }
91 }
92 samtools_process->close_in();
93 }));
94 loader_thread->detach();
95 return false;
96}
97
98template<typename ReaderType, typename RecordType>
99inline bool
100SeqReaderSamModule::read_transition(ReaderType& reader, RecordType& record)
101{
102 (void)reader;
103 (void)record;
104 return false;
105}
106
107template<typename ReaderType, typename RecordType>
108inline bool
109SeqReaderSamModule::read_file(ReaderType& reader, RecordType& record)
110{
111 if (!reader.file_at_end(samtools_process->out)) {
112 reader.readline_file(record.header, samtools_process->out);
113 reader.readline_file(record.seq, samtools_process->out);
114 reader.readline_file(tmp, samtools_process->out);
115 reader.readline_file(record.qual, samtools_process->out);
116 return true;
117 }
118 return false;
119}
121
122} // namespace btllib
123
124#endif
Definition: bloom_filter.hpp:16
void check_error(bool condition, const std::string &msg)
void log_info(const std::string &msg)