cuSBF
Loading...
Searching...
No Matches
Public Member Functions | List of all members
cusbf::detail::FastxBufferReader Class Reference

FASTA/FASTQ parser over a contiguous in-memory buffer. More...

#include <fastx_buffer_reader.hpp>

Public Member Functions

 FastxBufferReader (std::string_view data, std::string_view source_name="<buffer>")
 Constructs a reader over a contiguous in-memory FASTA/FASTQ buffer.
 
Result< boolnextRecord (FastxRecord &record)
 Reads the next record into record.
 
std::string_view buffer () const noexcept
 Entire mmap or owned buffer backing this reader.
 
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.
 

Detailed Description

FASTA/FASTQ parser over a contiguous in-memory buffer.

Definition at line 15 of file fastx_buffer_reader.hpp.

Constructor & Destructor Documentation

◆ FastxBufferReader()

cusbf::detail::FastxBufferReader::FastxBufferReader ( std::string_view  data,
std::string_view  source_name = "<buffer>" 
)
inlineexplicit

Constructs a reader over a contiguous in-memory FASTA/FASTQ buffer.

Parameters
dataEntire file or chunk payload.
source_nameLabel used in parse error messages.

Definition at line 23 of file fastx_buffer_reader.hpp.

24 : data_(data), source_name_(source_name) {}
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

Member Function Documentation

◆ appendNextRecord()

Result< std::optional< RecordRange > > cusbf::detail::FastxBufferReader::appendNextRecord ( FastxRecord record,
std::string &  sequence,
std::string_view &  buffer 
)
inline

Parses one record with optional zero-copy sequence views for single-line FASTA.

When the sequence fits one mmap line, returns a RecordRange into buffer instead of appending to sequence. Otherwise appends sequence bytes to sequence and returns an owned range offset.

Parameters
recordOutput header (sequence may stay empty on zero-copy path).
sequenceGrowing buffer for multi-line or owned FASTA sequence data.
bufferSet to the full mmap view on first zero-copy record.
Returns
Record byte range, std::nullopt at end-of-buffer, or an error.

Definition at line 91 of file fastx_buffer_reader.hpp.

91 {
92 record.header.clear();
93 record.sequence.clear();
94
95 const auto header = readHeaderLine();
96 if (!header) {
97 return Err(header.error());
98 }
99 if (header->empty()) {
100 return std::nullopt;
101 }
102
103 const char header_tag = header->front();
104 if (format_ == FastxFormat::unknown) {
105 if (header_tag == '>') {
106 format_ = FastxFormat::fasta;
107 } else if (header_tag == '@') {
108 format_ = FastxFormat::fastq;
109 } else {
110 return Err(
111 parseError("expected FASTA or FASTQ header", fastx_column_at(*header, 0))
112 );
113 }
114 }
115
116 const char expected_header = format_ == FastxFormat::fasta ? '>' : '@';
118 return Err(parseError(
119 "mixed FASTA and FASTQ records are not supported", fastx_column_at(*header, 0)
120 ));
121 }
122
123 record.header.assign(header->substr(1));
124 if (format_ == FastxFormat::fasta) {
125 const uint64_t sequence_offset = static_cast<uint64_t>(position_);
126 const std::string_view line = readLine();
127 if (line.empty()) {
128 return Err(parseError("FASTA record missing sequence", fastx_column_at(line, 0)));
129 }
130 if (!line.empty() && line.front() == '>') {
131 pending_header_.assign(line);
132 return Err(parseError("FASTA record missing sequence", fastx_column_at(line, 0)));
133 }
134
135 if (position_ < data_.size() && data_[position_] != '>') {
136 const uint64_t owned_offset = static_cast<uint64_t>(sequence.size());
137 sequence.append(line.data(), line.size());
138 CUSBF_TRY(readFastaSequence(sequence));
139 return RecordRange{
141 static_cast<uint64_t>(sequence.size()) - owned_offset,
142 };
143 }
144
145 if (position_ < data_.size() && data_[position_] == '>') {
146 pending_header_.assign(readLine());
147 }
148
149 if (buffer.empty()) {
150 buffer = data_;
151 }
152 return RecordRange{sequence_offset, static_cast<uint64_t>(line.size())};
153 }
154
155 const uint64_t sequence_offset = static_cast<uint64_t>(sequence.size());
156 CUSBF_TRY(readFastqSequence(sequence));
157 return RecordRange{
159 static_cast<uint64_t>(sequence.size()) - sequence_offset,
160 };
161 }
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).
Definition error.hpp:246
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).
Definition Fastx.hpp:268
@ fasta
FASTA (> headers).
@ fastq
FASTQ (@ headers).
@ unknown
Format not yet determined from the first header.
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
Definition error.hpp:219
Here is the call graph for this function:

◆ buffer()

std::string_view cusbf::detail::FastxBufferReader::buffer ( ) const
inlinenoexcept

Entire mmap or owned buffer backing this reader.

Definition at line 74 of file fastx_buffer_reader.hpp.

74 {
75 return data_;
76 }
Here is the caller graph for this function:

◆ nextRecord()

Result< bool > cusbf::detail::FastxBufferReader::nextRecord ( FastxRecord record)
inline

Reads the next record into record.

Parameters
recordOutput record, cleared before fill.
Returns
false at end-of-buffer, true when a record was read, or an error.

Definition at line 32 of file fastx_buffer_reader.hpp.

32 {
33 record.header.clear();
34 record.sequence.clear();
35
36 const auto header = readHeaderLine();
37 if (!header) {
38 return Err(header.error());
39 }
40 if (header->empty()) {
41 return false;
42 }
43
44 const char header_tag = header->front();
45 if (format_ == FastxFormat::unknown) {
46 if (header_tag == '>') {
47 format_ = FastxFormat::fasta;
48 } else if (header_tag == '@') {
49 format_ = FastxFormat::fastq;
50 } else {
51 return Err(
52 parseError("expected FASTA or FASTQ header", fastx_column_at(*header, 0))
53 );
54 }
55 }
56
57 const char expected_header = format_ == FastxFormat::fasta ? '>' : '@';
59 return Err(parseError(
60 "mixed FASTA and FASTQ records are not supported", fastx_column_at(*header, 0)
61 ));
62 }
63
64 record.header.assign(header->substr(1));
65 if (format_ == FastxFormat::fasta) {
66 CUSBF_TRY(readFastaSequence(record.sequence));
67 } else {
68 CUSBF_TRY(readFastqSequence(record.sequence));
69 }
70 return true;
71 }
Here is the call graph for this function:

The documentation for this class was generated from the following file: