blob: 9b7d253a2596c9ee77d05c1874aa23fb5e013adb [file] [log] [blame]
Ed Tanous911ac312017-08-15 09:37:42 -07001#pragma once
2
3#include <zlib.h>
4#include <cstring>
5#include <string>
6
7inline bool gzip_inflate(const std::string& compressedBytes,
8 std::string& uncompressedBytes) {
9 if (compressedBytes.empty()) {
10 uncompressedBytes = compressedBytes;
11 return true;
12 }
13
14 uncompressedBytes.clear();
15
16 unsigned half_length = compressedBytes.size() / 2;
17
18 z_stream strm{};
19
20 // The following line is nolint because we're declaring away constness.
21 // It's not clear why the input buffers on zlib aren't const, so this is a
22 // bit of a cheat for the moment
23 strm.next_in = (Bytef*)compressedBytes.data(); // NOLINT
24 strm.avail_in = compressedBytes.size();
25 strm.total_out = 0;
26 strm.zalloc = Z_NULL;
27 strm.zfree = Z_NULL;
28
29 bool done = false;
30
31 if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) {
32 return false;
33 }
34
35 while (!done) {
36 // If our output buffer is too small
37 if (strm.total_out >= uncompressedBytes.size()) {
38 uncompressedBytes.resize(uncompressedBytes.size() + half_length);
39 }
40
41 strm.next_out =
42 (Bytef*)(uncompressedBytes.data() + strm.total_out); // NOLINT
43 strm.avail_out =
44 ((uLong)uncompressedBytes.size() - strm.total_out); // NOLINT
45
46 // Inflate another chunk.
47 int err = inflate(&strm, Z_SYNC_FLUSH);
48 if (err == Z_STREAM_END) {
49 done = true;
50 } else if (err != Z_OK) {
51 break;
52 }
53 }
54
55 return inflateEnd(&strm) == Z_OK;
56}