24 template <
typename OutputType>
void decompress(OutputType&
output,
const char*
data, std::size_t size)
const
28 inflate_s.zalloc = Z_NULL;
29 inflate_s.zfree = Z_NULL;
30 inflate_s.opaque = Z_NULL;
31 inflate_s.avail_in = 0;
32 inflate_s.next_in = Z_NULL;
42 constexpr int window_bits = 15 + 32;
44#pragma GCC diagnostic push
45#pragma GCC diagnostic ignored "-Wold-style-cast"
46 if (inflateInit2(&inflate_s, window_bits) != Z_OK)
48 throw std::runtime_error(
"inflate init failed");
50#pragma GCC diagnostic pop
51 inflate_s.next_in =
reinterpret_cast<z_const Bytef*
>(
data);
55 std::uint64_t size_64 = size * 2;
56 if (size_64 > std::numeric_limits<unsigned int>::max())
58 inflateEnd(&inflate_s);
59 throw std::runtime_error(
"size arg is too large to fit into unsigned int type x2");
62 if (size >
max_ || (size * 2) >
max_)
64 inflateEnd(&inflate_s);
65 throw std::runtime_error(
"size may use more memory than intended when decompressing");
67 inflate_s.avail_in =
static_cast<unsigned int>(size);
68 std::size_t size_uncompressed = 0;
71 std::size_t resize_to = size_uncompressed + 2 * size;
74 inflateEnd(&inflate_s);
75 throw std::runtime_error(
76 "size of output string will use more memory then intended when decompressing");
79 inflate_s.avail_out =
static_cast<unsigned int>(2 * size);
80 inflate_s.next_out =
reinterpret_cast<Bytef*
>(&
output[0] + size_uncompressed);
81 int ret = inflate(&inflate_s, Z_FINISH);
82 if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR)
84 std::string error_msg = inflate_s.msg;
85 inflateEnd(&inflate_s);
86 throw std::runtime_error(error_msg);
89 size_uncompressed += (2 * size - inflate_s.avail_out);
90 }
while (inflate_s.avail_out == 0);
91 inflateEnd(&inflate_s);
92 output.resize(size_uncompressed);