24 #ifndef STATICLIB_COMPRESS_LZMA_SINK_HPP
25 #define STATICLIB_COMPRESS_LZMA_SINK_HPP
32 #include <type_traits>
36 #include "staticlib/config.hpp"
37 #include "staticlib/io.hpp"
38 #include "staticlib/support.hpp"
48 template <
typename Sink,
int compression_level = 6, std::
size_t buf_size = 4096 >
57 std::array<char, buf_size> buf;
71 sink(std::move(sink)),
73 lzma_stream* stream =
static_cast<lzma_stream*
> (std::malloc(
sizeof(lzma_stream)));
75 "Error creating lzma stream: 'malloc' failed"));
76 *stream = LZMA_STREAM_INIT;
77 auto err = ::lzma_easy_encoder(stream, compression_level, LZMA_CHECK_CRC64);
79 "Error initializing LZMA stream, code: [" + sl::support::to_string(err) +
"]"));
84 if (
nullptr == strm)
return;
85 auto deferred = sl::support::defer([
this]() STATICLIB_NOEXCEPT {
86 ::lzma_end(this->strm);
90 strm->next_in =
nullptr;
92 strm->next_out =
reinterpret_cast<uint8_t*
>(buf.data());
93 strm->avail_out = buf.size();
97 auto err = ::lzma_code(strm, LZMA_FINISH);
100 sl::io::write_all(sink, {buf.data(), buf.size() - strm->avail_out});
101 strm->next_out =
reinterpret_cast<uint8_t*
>(buf.data());
102 strm->avail_out = buf.size();
105 case LZMA_STREAM_END:
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 uint8_t*
>(span.data());
167 strm->avail_in =
static_cast<size_t> (span.size());
168 strm->next_out =
reinterpret_cast<uint8_t*
>(buf.data());
169 strm->avail_out = buf.size();
171 while (strm->avail_in > 0) {
172 auto err = ::lzma_code(strm, LZMA_RUN);
175 sl::io::write_all(sink, {buf.data(), buf.size() - strm->avail_out});
176 strm->next_out =
reinterpret_cast<uint8_t*
>(buf.data());
177 strm->avail_out = buf.size();
180 "LZMA error code: [" + sl::support::to_string(err) +
"]"));
183 return span.size_signed();
214 template <
typename Sink,
215 class =
typename std::enable_if<!std::is_lvalue_reference<Sink>::value>::type>
227 template <
typename Sink>
230 sl::io::make_reference_sink(sink));