#pragma once #include <solanaceae/file/file2.hpp> #include <memory> #include <zstd.h> // zstd compression wrapper over another file // WARNING: only supports sequential writes struct File2ZSTDW : public File2I { File2I& _real_file; // TODO: hide this detail? std::unique_ptr<ZSTD_CCtx, decltype(&ZSTD_freeCCtx)> _cctx{ZSTD_createCCtx(), &ZSTD_freeCCtx}; File2ZSTDW(File2I& real); virtual ~File2ZSTDW(void); bool isGood(void) override; // for simplicity and potential future seekability each write is its own frame bool write(const ByteSpan data, int64_t pos = -1) override; std::variant<ByteSpan, std::vector<uint8_t>> read(uint64_t size, int64_t pos = -1) override; }; // zstd decompression wrapper over another file // WARNING: only supports sequential reads // TODO: add seeking support (use frames) struct File2ZSTDR : public File2I { File2I& _real_file; // TODO: hide this detail? std::unique_ptr<ZSTD_DCtx, decltype(&ZSTD_freeDCtx)> _dctx{ZSTD_createDCtx(), &ZSTD_freeDCtx}; std::vector<uint8_t> _in_buffer; std::vector<uint8_t> _out_buffer; std::vector<uint8_t> _decompressed_buffer; // retains decompressed unread data between read() calls ZSTD_inBuffer _z_input{nullptr, 0, 0}; File2ZSTDR(File2I& real); virtual ~File2ZSTDR(void) {} bool isGood(void) override; bool write(const ByteSpan data, int64_t pos = -1) override; std::variant<ByteSpan, std::vector<uint8_t>> read(uint64_t size, int64_t pos = -1) override; private: bool feedInput(std::variant<ByteSpan, std::vector<uint8_t>>&& read_buff); };