24 #ifndef STATICLIB_COMPRESS_DEFLATE_SINK_HPP
25 #define STATICLIB_COMPRESS_DEFLATE_SINK_HPP
31 #include <type_traits>
35 #include "staticlib/config.hpp"
36 #include "staticlib/io.hpp"
37 #include "staticlib/support.hpp"
47 template <
typename Sink,
int compression_level = 6, std::
size_t buf_size = 4096>
56 std::array<char, buf_size> buf;
70 sink(std::move(sink)),
72 z_stream* stream =
static_cast<z_stream*
> (std::malloc(
sizeof(z_stream)));
74 "Error creating deflate stream: 'malloc' failed"));
75 std::memset(stream, 0,
sizeof (z_stream));
76 auto err = deflateInit2(stream, compression_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
78 "Error initializing deflate stream: [" + ::zError(err) +
"]"));
83 if (
nullptr == strm)
return;
84 auto deferred = sl::support::defer([
this]() STATICLIB_NOEXCEPT {
85 ::deflateEnd(this->strm);
89 strm->next_in =
nullptr;
91 strm->next_out =
reinterpret_cast<unsigned char*
> (buf.data());
92 strm->avail_out =
static_cast<uInt
> (buf.size());
94 bool deflating =
true;
96 auto err = ::deflate(strm, Z_FINISH);
100 sl::io::write_all(sink, {buf.data(), buf.size() - strm->avail_out});
101 strm->next_out =
reinterpret_cast<unsigned char*
> (buf.data());
102 strm->avail_out =
static_cast<uInt
> (buf.size());
106 sl::io::write_all(sink, {buf.data(), buf.size() - strm->avail_out});
138 sink(std::move(other.sink)),
139 buf(std::move(other.buf)),
141 other.strm =
nullptr;
151 sink = std::move(other.sink);
152 buf = std::move(other.buf);
154 other.strm =
nullptr;
164 std::streamsize
write(sl::io::span<const char> span) {
166 strm->next_in =
reinterpret_cast<const unsigned char*
> (span.data());
167 strm->avail_in =
static_cast<uInt
> (span.size());
168 strm->next_out =
reinterpret_cast<unsigned char*
> (buf.data());
169 strm->avail_out =
static_cast<uInt
> (buf.size());
171 while(strm->avail_in > 0) {
172 auto err = ::deflate(strm, Z_NO_FLUSH);
175 sl::io::write_all(sink, {buf.data(), buf.size() - strm->avail_out});
176 strm->next_out =
reinterpret_cast<unsigned char*
> (buf.data());
177 strm->avail_out =
static_cast<uInt
> (buf.size());
180 "Deflate error: [" + ::zError(err) +
"]"));
183 return span.size_signed();
215 template <
typename Sink,
216 class =
typename std::enable_if<!std::is_lvalue_reference<Sink>::value>::type>
228 template <
typename Sink>
231 sl::io::make_reference_sink(sink));