42 using ZLIBByte =
unsigned char;
43 static_assert(
sizeof(
typename Serialization::Byte) ==
sizeof(ZLIBByte));
45 struct BlockDecompressor {
46 using ByteType = ZLIBByte;
48 void operator()(std::span<const ByteType> in, std::span<ByteType> out)
const {
49 uLongf out_len = out.size();
50 uLong in_len = in.size();
51 if (uncompress(out.data(), &out_len, in.data(), in_len) != Z_OK)
52 throw IOError(
"(ZLIBCompressor) Error upon decompression");
53 if (out_len != out.size())
54 throw IOError(
"(ZLIBCompressor) Unexpected decompressed size");
61 explicit constexpr ZLIB(Options opts = {})
62 : _opts(std::move(opts))
65 template<std::
integral HeaderType = std::
size_t>
67 if (std::numeric_limits<HeaderType>::max() < in.size())
68 throw TypeError(
"Chosen HeaderType is too small for given number of bytes");
69 if (std::numeric_limits<HeaderType>::max() < _opts.block_size)
70 throw TypeError(
"Chosen HeaderType is too small for given block size");
72 auto [blocks, out] = _compress<HeaderType>(in.template as_span_of<const ZLIBByte>());
74 in.resize(blocks.compressed_size());
78 template<std::
integral HeaderType>
83 static ZLIB with(Options opts) {
84 return ZLIB{std::move(opts)};
88 template<std::
integral HeaderType>
89 auto _compress(std::span<const ZLIBByte> in)
const {
90 HeaderType block_size =
static_cast<HeaderType
>(_opts.block_size);
91 HeaderType size_in_bytes =
static_cast<HeaderType
>(in.size());
94 Serialization compressed;
95 std::vector<ZLIBByte> block_buffer;
96 std::vector<HeaderType> compressed_block_sizes;
97 block_buffer.reserve(compressBound(_opts.block_size));
98 compressed_block_sizes.reserve(blocks.number_of_blocks);
99 compressed.resize(block_buffer.capacity()*blocks.number_of_blocks);
101 HeaderType cur_in = 0;
102 HeaderType cur_out = 0;
103 auto out = compressed.template as_span_of<ZLIBByte>();
104 while (cur_in < size_in_bytes) {
106 const HeaderType cur_block_size = min(block_size, size_in_bytes - cur_in);
107 assert(cur_in + cur_block_size <= size_in_bytes);
109 uLongf out_len = block_buffer.capacity();
110 uLong in_len = cur_block_size;
111 if (compress2(block_buffer.data(), &out_len,
112 in.data() + cur_in, in_len,
113 _opts.compression_level) != Z_OK)
114 throw InvalidState(as_error(
"Error upon compression with ZLib"));
116 assert(cur_out + out_len <= out.size());
117 std::copy_n(block_buffer.data(),
119 out.data() + cur_out);
120 cur_in += cur_block_size;
122 compressed_block_sizes.push_back(
static_cast<HeaderType
>(out_len));
125 if (cur_in != size_in_bytes)
126 throw InvalidState(as_error(
"(ZLIBCompressor) unexpected number of bytes processed"));
128 return std::make_tuple(
void decompress(Serialization &in, const CompressedBlocks< HeaderType > &blocks, const Decompressor &block_decompressor)
Decompress compressed data.
Definition decompress.hpp:26