49 ZStream(std::optional<ZlibCompressionMode> mode) {
55 strm.next_in = Z_NULL;
62 if (mode.has_value()) {
64 case ZlibCompressionMode::DEFLATE:
65 ret = inflateInit2(&strm, -MAX_WBITS);
67 case ZlibCompressionMode::ZLIB:
68 ret = inflateInit2(&strm, MAX_WBITS);
70 case ZlibCompressionMode::GZIP:
71 ret = inflateInit2(&strm, 16 + MAX_WBITS);
74 throw std::runtime_error(
"unknown Zlib compression mode");
78 ret = inflateInit2(&strm, 32 + MAX_WBITS);
82 throw std::runtime_error(strm.msg);
93 ZStream(
const ZStream&) =
delete;
94 ZStream(ZStream&&) =
delete;
95 ZStream& operator=(
const ZStream&) =
delete;
96 ZStream& operator=(ZStream&&) =
delete;
102 typedef I<
decltype(I<
decltype(ZStream::strm)>::avail_out)> ZoutSize;
111 my_zstr(options.mode),
113 my_buffer(
sanisizer::cap<I<decltype(my_buffer.size())> >(
sanisizer::cap<ZoutSize>(options.buffer_size))),
119 std::size_t
read(
unsigned char* buffer, std::size_t n) {
120 return read0<ZoutSize>(buffer, n);
128 template<
typename InSize>
129 std::size_t read0(
unsigned char* buffer, std::size_t n) {
130 return safe_read<ZoutSize>(buffer, n, [
this](
unsigned char* buffer, ZoutSize n) -> ZoutSize {
131 return this->read_internal<InSize>(buffer, n);
139 template<
typename InSize_>
140 ZoutSize read_internal(
unsigned char* buffer, ZoutSize n) {
143 if (my_cached_length) {
144 const auto limit = std::min(remaining, my_cached_length);
145 std::copy_n(my_buffer.data() + my_cached_start, limit, buffer);
148 my_cached_start += limit;
149 my_cached_length -= limit;
153 while (!my_finished) {
154 if (my_zstr.strm.avail_in == 0) {
156 my_zstr.strm.avail_in = to_use;
158 my_zstr.strm.next_in =
const_cast<unsigned char*
>(my_input);
166 my_zstr.strm.avail_out = my_buffer.size();
167 my_zstr.strm.next_out = my_buffer.data();
168 auto ret = inflate(&(my_zstr.strm), Z_NO_FLUSH);
175 throw std::runtime_error(
"zlib error");
181 const ZoutSize nread = my_buffer.size() - my_zstr.strm.avail_out;
182 if (nread < remaining) {
183 std::copy_n(my_buffer.data(), nread, buffer);
187 std::copy_n(my_buffer.data(), remaining, buffer);
188 my_cached_start = remaining;
189 my_cached_length = nread - remaining;
196 return n - remaining;
201 std::vector<unsigned char> my_buffer;
202 const unsigned char* my_input;
203 std::size_t my_length;
204 ZoutSize my_cached_start = 0, my_cached_length = 0;
205 bool my_finished =
false;