cuSBF
Loading...
Searching...
No Matches
fastx_file_buffer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <filesystem>
5#include <format>
6#include <fstream>
7#include <memory>
8#include <string>
9#include <string_view>
10#include <vector>
11
12#include <cusbf/error.hpp>
13
14#if defined(__linux__)
15 #include <fcntl.h>
16 #include <sys/mman.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19#endif
20
21#include <cusbf/gzstreambuf.hpp>
22
23namespace cusbf::detail {
24
27 public:
28 FastxFileBuffer() = default;
32 *this = std::move(other);
33 }
34
36 if (this != &other) {
37 release();
38 owned_storage_ = std::move(other.owned_storage_);
39 data_ = other.data_;
40 size_ = other.size_;
41#if defined(__linux__)
42 mapped_ = other.mapped_;
43 mapped_size_ = other.mapped_size_;
44 other.mapped_ = nullptr;
45 other.mapped_size_ = 0;
46#endif
47 other.data_ = nullptr;
48 other.size_ = 0;
49 }
50 return *this;
51 }
52
54 release();
55 }
56
64 const std::filesystem::path& path
65 ) {
66 auto buffer = std::make_unique<FastxFileBuffer>();
67 CUSBF_TRY(buffer->load_from_path(path));
68 return buffer;
69 }
70
72 [[nodiscard]] std::string_view data() const noexcept {
73 return std::string_view{data_, size_};
74 }
75
78 return size_ == 0;
79 }
80
81 private:
82 std::vector<char> owned_storage_;
83 const char* data_{nullptr};
84 size_t size_{0};
85
86#if defined(__linux__)
87 void* mapped_{nullptr};
88 size_t mapped_size_{0};
89#endif
90
91 void release() {
92#if defined(__linux__)
93 if (mapped_ != nullptr) {
95 mapped_ = nullptr;
96 mapped_size_ = 0;
97 }
98#endif
99 owned_storage_.clear();
100 data_ = nullptr;
101 size_ = 0;
102 }
103
104 [[nodiscard]] Result<void> load_from_path(const std::filesystem::path& path) {
105 const std::string path_string = path.string();
106
107#if defined(__linux__)
108 const int fd = ::open(path_string.c_str(), O_RDONLY);
109 if (fd == -1) {
110 return Err(Error::io(std::format("Failed to open FASTA/FASTQ file: {}", path_string)));
111 }
112
113 struct stat file_status{};
114 if (::fstat(fd, &file_status) != 0 || file_status.st_size < 0) {
115 ::close(fd);
116 return Err(Error::io(std::format("Failed to stat FASTA/FASTQ file: {}", path_string)));
117 }
118
119 if (file_status.st_size == 0) {
120 ::close(fd);
121 return {};
122 }
123
124 mapped_size_ = static_cast<size_t>(file_status.st_size);
126 ::close(fd);
127 if (mapped_ == MAP_FAILED) {
128 mapped_ = nullptr;
129 mapped_size_ = 0;
130 return Err(Error::io(std::format("Failed to mmap FASTA/FASTQ file: {}", path_string)));
131 }
132
133 data_ = static_cast<const char*>(mapped_);
134 size_ = mapped_size_;
135 return {};
136#endif
137
138 std::ifstream input(path_string, std::ios::binary);
139 if (!input.is_open()) {
140 return Err(Error::io(std::format("Failed to open FASTA/FASTQ file: {}", path_string)));
141 }
142 input.seekg(0, std::ios::end);
143 const auto file_size = input.tellg();
144 if (file_size < 0) {
145 return Err(Error::io(std::format("Failed to size FASTA/FASTQ file: {}", path_string)));
146 }
147 owned_storage_.resize(static_cast<size_t>(file_size));
148 input.seekg(0, std::ios::beg);
149 if (!owned_storage_.empty()) {
150 input.read(owned_storage_.data(), static_cast<std::streamsize>(owned_storage_.size()));
151 if (!input) {
152 return Err(
153 Error::io(std::format("Failed to read FASTA/FASTQ file: {}", path_string))
154 );
155 }
156 }
157 data_ = owned_storage_.data();
158 size_ = owned_storage_.size();
159 return {};
160 }
161};
162
164[[nodiscard]] inline bool fastx_file_supports_memory_map(const std::filesystem::path& path) {
165 return !isGzipFile(path);
166}
167
168} // namespace cusbf::detail
Read-only contiguous file payload for in-memory FASTX parsing.
FastxFileBuffer & operator=(FastxFileBuffer &&other) noexcept
FastxFileBuffer(FastxFileBuffer &&other) noexcept
static Result< std::unique_ptr< FastxFileBuffer > > load(const std::filesystem::path &path)
Loads an uncompressed file via mmap (Linux) or read into memory.
bool empty() const noexcept
True when the file is empty or load produced no bytes.
FastxFileBuffer(const FastxFileBuffer &)=delete
std::string_view data() const noexcept
Contiguous read-only file bytes.
FastxFileBuffer & operator=(const FastxFileBuffer &)=delete
#define CUSBF_TRY(expr)
Propagates a cusbf::Result failure from the enclosing function (GNU statement expression).
Definition error.hpp:246
bool isGzipFile(const std::filesystem::path &path)
True when path begins with the gzip magic bytes (0x1F, 0x8B).
bool fastx_file_supports_memory_map(const std::filesystem::path &path)
True when path is not gzip-compressed (mmap path is usable).
consteval bool separatorPositionAlwaysEncodesInvalid(char *input, uint64_t separatorPosition, uint64_t index)
Recursively tests whether placing the separator byte at any position in an input of valid bytes alway...
Definition Alphabet.cuh:37
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
Definition error.hpp:219
static Error io(std::string message)
Definition error.hpp:119
Fallible API result: cuda::std::expected<T, Error> with cuSBF factories.
Definition error.hpp:152