forked from peadar/pstack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinflate.cc
55 lines (49 loc) · 1.63 KB
/
inflate.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "libpstack/inflatereader.h"
#include "libpstack/util.h"
#include <zlib.h>
InflateReader::InflateReader(size_t inflatedSize, const Reader &upstream)
: MemReader(std::string("inflated content from ") + stringify(upstream),
inflatedSize, new char[inflatedSize])
{
char xferbuf[32768];
z_stream stream{};
int window = 15;
if (inflateInit2(&stream, window) != Z_OK)
throw (Exception() << "inflateInit2 failed");
stream.avail_out = inflatedSize;
using bytep = Bytef *;
stream.next_out = bytep(data);
bool eof = false;
size_t inputOffset = 0;
if (verbose >= 2)
*debug << "inflating" << upstream << "...";
for (bool done = false; !done; ) {
if (stream.avail_in == 0 && !eof) {
// keep the input buffer full
stream.avail_in = upstream.read(inputOffset, sizeof xferbuf, xferbuf);
inputOffset += stream.avail_in;
stream.next_in = bytep(xferbuf);
if (stream.avail_in == 0)
eof = true;
}
size_t writeChunk = stream.avail_out;
switch (inflate(&stream, eof ? Z_FINISH : Z_SYNC_FLUSH)) {
case Z_STREAM_END:
done = true;
// fallthrough
case Z_OK:
if (verbose >= 2)
*debug << " [" << writeChunk - stream.avail_out << "]";
break;
default:
throw (Exception() << "inflate failed");
}
}
inflateEnd(&stream);
if (verbose >= 2)
*debug << " total " << inflatedSize << "\n";
}
InflateReader::~InflateReader()
{
delete[] data;
}