cuSBF
Loading...
Searching...
No Matches
gzstreambuf.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <filesystem>
6#include <format>
7#include <istream>
8#include <memory>
9#include <streambuf>
10#include <string_view>
11
12#include <zlib.h>
13#include <cusbf/error.hpp>
14
15namespace cusbf::detail {
16
18class GzStreambuf : public std::streambuf {
19 public:
20 GzStreambuf(const GzStreambuf&) = delete;
24
31 const std::filesystem::path& path
32 ) {
33 auto streambuf = std::unique_ptr<GzStreambuf>(new GzStreambuf(path));
34 if (!streambuf->file_) {
35 return Err(Error::io(std::format("Failed to open gzip file: {}", path.string())));
36 }
37 return streambuf;
38 }
39
40 ~GzStreambuf() override {
41 if (file_) {
42 gzclose(file_);
43 }
44 }
45
46 protected:
47 int_type underflow() override {
48 if (gptr() < egptr()) {
49 return traits_type::to_int_type(*gptr());
50 }
51
52 auto bytesRead = gzread(file_, buffer_, kBufferSize);
53 if (bytesRead <= 0) {
54 return traits_type::eof();
55 }
56
57 setg(buffer_, buffer_, buffer_ + bytesRead);
58 return traits_type::to_int_type(*gptr());
59 }
60
61 private:
62 static constexpr std::size_t kBufferSize = 8192;
63
64 explicit GzStreambuf(const std::filesystem::path& path)
65 : file_(gzopen(path.string().c_str(), "rb")) {
66 setg(buffer_, buffer_, buffer_);
67 }
68
69 gzFile file_;
70 char buffer_[kBufferSize];
71};
72
74class GzIstream : public std::istream {
75 public:
82 const std::filesystem::path& path
83 ) {
84 auto streambuf = GzStreambuf::open(path);
85 if (!streambuf) {
86 return Err(streambuf.error());
87 }
88 return std::unique_ptr<GzIstream>(new GzIstream(std::move(*streambuf)));
89 }
90
91 private:
92 explicit GzIstream(std::unique_ptr<GzStreambuf> streambuf)
93 : std::istream(nullptr), sb_(std::move(streambuf)) {
94 rdbuf(sb_.get());
95 }
96
97 std::unique_ptr<GzStreambuf> sb_;
98};
99
101inline bool isGzipFile(const std::filesystem::path& path) {
102 FILE* f = std::fopen(path.string().c_str(), "rb");
103 if (!f) {
104 return false;
105 }
106 uint8_t magic[2];
107 size_t n = std::fread(magic, 1, 2, f);
108 std::fclose(f);
109 return n == 2 && magic[0] == 0x1F && magic[1] == 0x8B;
110}
111
112} // namespace cusbf::detail
std::istream adapter for GzStreambuf.
static Result< std::unique_ptr< GzIstream > > open(const std::filesystem::path &path)
Opens a gzip file as an input stream.
std::streambuf over a gzip file (zlib gzread).
GzStreambuf(GzStreambuf &&)=delete
int_type underflow() override
static Result< std::unique_ptr< GzStreambuf > > open(const std::filesystem::path &path)
Opens path for binary gzip read.
GzStreambuf & operator=(GzStreambuf &&)=delete
GzStreambuf(const GzStreambuf &)=delete
GzStreambuf & operator=(const GzStreambuf &)=delete
bool isGzipFile(const std::filesystem::path &path)
True when path begins with the gzip magic bytes (0x1F, 0x8B).
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