10#if defined(__aarch64__) || defined(_M_ARM64)
13#if defined(__ARM_FEATURE_SVE2)
15#elif defined(__x86_64__) || defined(_M_X64)
16 #include <immintrin.h>
31#if (defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) && !defined(__CUDACC__)
32[[gnu::target(
"avx2")]] [[
nodiscard]]
inline size_t
36 while (data.size() -
position >= 32) {
51#if defined(__ARM_FEATURE_SVE)
68#if defined(__aarch64__) || defined(_M_ARM64)
72 while (data.size() -
position >= 16) {
94#if defined(__ARM_FEATURE_SVE)
96#elif defined(__aarch64__) || defined(_M_ARM64)
98#elif (defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) && !defined(__CUDACC__)
133 const auto header = readHeaderLine();
135 return Err(header.error());
137 if (header->empty()) {
149 parseError(
"expected FASTA or FASTQ header",
fastx_column_at(*header, 0))
156 return Err(parseError(
157 "mixed FASTA and FASTQ records are not supported",
fastx_column_at(*header, 0)
161 record.header.assign(header->substr(1));
192 const auto header = readHeaderLine();
194 return Err(header.error());
196 if (header->empty()) {
208 parseError(
"expected FASTA or FASTQ header",
fastx_column_at(*header, 0))
215 return Err(parseError(
216 "mixed FASTA and FASTQ records are not supported",
fastx_column_at(*header, 0)
220 record.header.assign(header->substr(1));
223 const std::string_view line = readLine();
227 if (!line.empty() && line.front() ==
'>') {
231 if (position_ < data_.size() && data_[position_] !=
'>') {
233 sequence.append(line.data(), line.size());
248 CUSBF_TRY(readFastqSequence(sequence, sequence.size()));
256 std::string_view data_;
257 std::string_view source_name_;
262 [[
nodiscard]] Error parseError(std::string_view message,
uint32_t column)
const {
269 [[
nodiscard]] std::string_view readLine() {
270 if (position_ >= data_.size()) {
276 const std::string_view line = data_.substr(position_, end - position_);
278 if (position_ < data_.size() && data_[position_] ==
'\r') {
281 if (position_ < data_.size() && data_[position_] ==
'\n') {
289 while (position_ < data_.size()) {
290 const std::string_view line = readLine();
295 return std::string_view{};
298 [[
nodiscard]] Result<void> readFastaSequence(std::string& sequence) {
299 while (position_ < data_.size()) {
300 if (data_[position_] ==
'>') {
303 const std::string_view line = readLine();
304 sequence.append(line.data(), line.size());
312 while (position_ < data_.size()) {
313 const std::string_view line = readLine();
315 if (!line.empty() && line.front() ==
'+') {
319 sequence.append(line.data(), line.size());
321 return Err(parseError(
322 "unterminated FASTQ record: missing '+' separator",
331 const std::string_view line = readLine();
335 return Err(parseError(
336 "FASTQ quality length exceeds sequence length",
342 return Err(parseError(
343 "FASTQ quality length does not match sequence length",
FASTA/FASTQ parser over a contiguous in-memory buffer.
FastxBufferReader(std::string_view data, std::string_view source_name="<buffer>")
Constructs a reader over a contiguous in-memory FASTA/FASTQ buffer.
Result< bool > nextRecord(FastxRecord &record)
Reads the next record into record.
Result< std::optional< RecordRange > > appendNextRecord(FastxRecord &record, std::string &sequence, std::string_view &buffer)
Parses one record with optional zero-copy sequence views for single-line FASTA.
std::string_view buffer() const noexcept
Entire mmap or owned buffer backing this reader.
#define CUSBF_TRY(expr)
Propagates a cusbf::Result failure from the enclosing function (GNU statement expression).
size_t fastx_line_end_scalar(std::string_view data, size_t position)
uint32_t fastx_column_at(std::string_view line, size_t byte_index)
1-based column at byte_index within line (clamped to the line end).
uint32_t fastx_quality_short_column(std::string_view line)
1-based column where a quality run ends too short (position after the last byte).
uint32_t fastx_quality_excess_column(uint64_t quality_length, uint64_t expected_length, std::string_view line)
1-based column of the first quality byte that exceeds expected_length.
FastxFormat
Detected file format for a FASTA/FASTQ stream.
@ fasta
FASTA (> headers).
@ fastq
FASTQ (@ headers).
@ unknown
Format not yet determined from the first header.
size_t fastx_line_end(std::string_view data, size_t position)
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...
decltype(&fastx_line_end_scalar) fastx_line_end_fn
fastx_line_end_fn resolve_fastx_line_end()
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
static Error fastx_parse(SourceLocation site, std::string_view detail)
Ordered non-overlapping byte range for one record inside a dense sequence batch.
Fallible API result: cuda::std::expected<T, Error> with cuSBF factories.
static SourceLocation fastx(std::string_view file, uint32_t line, uint32_t column)
A single sequence record extracted from a FASTA/FASTQ stream.