6 #include "lz4_streambuf.h"
11 lz4c_steambuf::lz4c_steambuf(std::ostream& sink,
size_t buf_size)
14 , dest_buf(LZ4F_compressBound(buf_size, nullptr)) {
15 auto errCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
16 if(LZ4F_isError(errCode) != 0)
17 throw std::runtime_error(std::string(
"Failed to create LZ4 context: ") + LZ4F_getErrorName(errCode));
18 size_t sz = LZ4F_compressBegin(ctx, dest_buf.data(), dest_buf.capacity(),
nullptr);
19 if(LZ4F_isError(sz) != 0)
20 throw std::runtime_error(std::string(
"Failed to start LZ4 compression: ") + LZ4F_getErrorName(sz));
21 setp(src_buf.data(), src_buf.data() + src_buf.size() - 1);
22 sink.write(dest_buf.data(), sz);
25 lz4c_steambuf::~lz4c_steambuf() { close(); }
27 void lz4c_steambuf::close() {
30 lz4c_steambuf::sync();
31 auto sz = LZ4F_compressEnd(ctx, dest_buf.data(), dest_buf.capacity(),
nullptr);
32 if(LZ4F_isError(sz) != 0)
33 throw std::runtime_error(std::string(
"Failed to finish LZ4 compression: ") + LZ4F_getErrorName(sz));
35 sink.write(dest_buf.data(), sz);
38 LZ4F_freeCompressionContext(ctx);
42 std::streambuf::int_type lz4c_steambuf::sync() {
48 std::streambuf::int_type lz4c_steambuf::overflow(int_type ch) {
50 *pptr() =
static_cast<char_type
>(ch);
55 void lz4c_steambuf::compress_and_write() {
57 throw std::runtime_error(
"Cannot write to closed stream");
58 if(
auto orig_size = pptr() - pbase()) {
59 auto ret = LZ4F_compressUpdate(ctx, dest_buf.data(), dest_buf.capacity(), pbase(), orig_size,
nullptr);
60 if(LZ4F_isError(ret) != 0)
61 throw std::runtime_error(std::string(
"LZ4 compression failed: ") + LZ4F_getErrorName(ret));
63 sink.write(dest_buf.data(), ret);
68 lz4d_streambuf::lz4d_streambuf(std::istream& source,
size_t buf_size)
71 , dest_buf(4 * buf_size) {
72 auto ret = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
73 if(LZ4F_isError(ret) != 0)
74 throw std::runtime_error(std::string(
"Failed to create LZ4 context: ") + LZ4F_getErrorName(ret));
75 setg(src_buf.data(), src_buf.data(), src_buf.data());
78 lz4d_streambuf::~lz4d_streambuf() { LZ4F_freeDecompressionContext(ctx); }
80 std::streambuf::int_type lz4d_streambuf::underflow() {
81 auto written_size = 0UL;
83 if(offset == src_buf_size) {
84 src_str.read(src_buf.data(), src_buf.size());
85 src_buf_size =
static_cast<size_t>(src_str.gcount());
89 return traits_type::eof();
90 auto src_size = src_buf_size - offset;
91 auto dest_size = dest_buf.size();
92 auto ret = LZ4F_decompress(ctx, dest_buf.data(), &dest_size, src_buf.data() + offset, &src_size,
nullptr);
93 if(LZ4F_isError(ret) != 0)
94 throw std::runtime_error(std::string(
"LZ4 decompression failed: ") + LZ4F_getErrorName(ret));
95 written_size = dest_size;
97 }
while(written_size == 0);
98 setg(dest_buf.data(), dest_buf.data(), dest_buf.data() + written_size);
99 return traits_type::to_int_type(*gptr());