24#if defined(SEQAN3_HAS_BZIP2)
25# include <seqan3/contrib/stream/bz2_istream.hpp>
27#if defined(SEQAN3_HAS_ZLIB)
28# include <seqan3/contrib/stream/bgzf_istream.hpp>
30# include <seqan3/contrib/stream/gz_istream.hpp>
37namespace seqan3::detail
45template <std::ranges::forward_range ref_t, std::ranges::forward_range query_t>
46inline bool starts_with(ref_t && reference, query_t && query)
47 requires std::equality_comparable_with<std::ranges::range_reference_t<ref_t>,
48 std::ranges::range_reference_t<query_t>>
51 auto rend = std::ranges::end(reference);
54 auto qend = std::ranges::end(query);
79template <builtin_
character
char_t>
83 assert(primary_stream.good());
95 std::array<char, bgzf_compression::magic_header.
size()> magic_number{};
96 size_t read_chars = 0;
97 for (; read_chars < magic_number.size(); ++read_chars)
102 magic_number[read_chars] = *it;
107 for (
size_t i = 0; i < read_chars; ++i)
108 primary_stream.unget();
110 assert(primary_stream.good() &&
"`unget()` was called too many times on primary_stream.");
113 if (filename.has_extension())
114 extension = filename.extension().
string().substr(1);
117 [[maybe_unused]]
auto contains_extension = [](
auto compression_tag,
auto const & extension)
constexpr
120 != std::ranges::end(
decltype(compression_tag)::file_extensions);
124 if (read_chars == magic_number.size() && bgzf_compression::validate_header(
std::span{magic_number}))
126#if defined(SEQAN3_HAS_ZLIB)
127 if (contains_extension(gz_compression{}, extension) || contains_extension(bgzf_compression{}, extension))
128 filename.replace_extension();
130 return {
new contrib::basic_bgzf_istream<char_t>{primary_stream}, stream_deleter_default};
132 throw file_open_error{
"Trying to read from a bgzf file, but no ZLIB available."};
135 else if (starts_with(magic_number, gz_compression::magic_header))
137#if defined(SEQAN3_HAS_ZLIB)
138 if (contains_extension(gz_compression{}, extension) || contains_extension(bgzf_compression{}, extension))
139 filename.replace_extension();
141 return {
new contrib::basic_gz_istream<char_t>{primary_stream}, stream_deleter_default};
143 throw file_open_error{
"Trying to read from a gzipped file, but no ZLIB available."};
146 else if (starts_with(magic_number, bz2_compression::magic_header))
148#if defined(SEQAN3_HAS_BZIP2)
149 if (contains_extension(bz2_compression{}, extension))
150 filename.replace_extension();
152 return {
new contrib::basic_bz2_istream<char_t>{primary_stream}, stream_deleter_default};
154 throw file_open_error{
"Trying to read from a bzipped file, but no libbz2 available."};
157 else if (starts_with(magic_number, zstd_compression::magic_header))
159 throw file_open_error{
"Trying to read from a zst'ed file, but SeqAn does not yet support this."};
162 return {&primary_stream, stream_deleter_noop};
166template <builtin_
character
char_t>
170 return make_secondary_istream(primary_stream, p);
Provides seqan3::contrib::bgzf_thread_count.
Provides stream compression utilities.
Provides exceptions used in the I/O module.
Provides concepts that do not have equivalents in C++20.