-
Notifications
You must be signed in to change notification settings - Fork 233
Expand file tree
/
Copy pathccapi_inflate_stream.h
More file actions
103 lines (92 loc) · 3.12 KB
/
ccapi_inflate_stream.h
File metadata and controls
103 lines (92 loc) · 3.12 KB
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#ifndef INCLUDE_CCAPI_CPP_CCAPI_INFLATE_STREAM_H_
#define INCLUDE_CCAPI_CPP_CCAPI_INFLATE_STREAM_H_
#ifndef CCAPI_DECOMPRESS_BUFFER_SIZE
#define CCAPI_DECOMPRESS_BUFFER_SIZE (1 << 20)
#endif
#include "zlib.h"
namespace ccapi {
/**
* Due to Huobi using gzip instead of zip in data compression, we cannot use beast::zboost::system::inflate_stream. Therefore we have to create our own.
*/
class InflateStream {
public:
explicit InflateStream() {
this->windowBits = 15;
this->windowBitsOverride = 0;
this->istate.zalloc = Z_NULL;
this->istate.zfree = Z_NULL;
this->istate.opaque = Z_NULL;
this->istate.avail_in = 0;
this->istate.next_in = Z_NULL;
this->decompressBufferSize = CCAPI_DECOMPRESS_BUFFER_SIZE;
}
std::string toString() const {
std::string output = "InflateStream [windowBits = " + ccapi::toString(windowBits) + "]";
return output;
}
virtual ~InflateStream() {
if (!this->initialized) {
return;
}
int ret = inflateEnd(&this->istate);
if (ret != Z_OK) {
CCAPI_LOGGER_ERROR("error cleaning up zlib decompression state");
}
}
void setWindowBitsOverride(int windowBitsOverride) { this->windowBitsOverride = windowBitsOverride; }
boost::system::error_code init() {
int ret;
if (this->windowBitsOverride == 0) {
ret = inflateInit2(&this->istate, -1 * this->windowBits);
} else {
ret = inflateInit2(&this->istate, this->windowBitsOverride
// 31
);
}
if (ret != Z_OK) {
CCAPI_LOGGER_ERROR("decompress error");
return boost::system::error_code();
}
this->buffer.reset(new unsigned char[this->decompressBufferSize]);
this->initialized = true;
return boost::system::error_code();
}
boost::system::error_code decompress(uint8_t const* buf, size_t len, std::string& out) {
if (!this->initialized) {
CCAPI_LOGGER_ERROR("decompress error");
return boost::system::error_code();
}
this->istate.avail_in = len;
this->istate.next_in = const_cast<unsigned char*>(buf);
do {
this->istate.avail_out = this->decompressBufferSize;
this->istate.next_out = this->buffer.get();
int ret = inflate(&this->istate, Z_SYNC_FLUSH);
if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
CCAPI_LOGGER_ERROR("decompress error");
return boost::system::error_code();
}
out.append(reinterpret_cast<char*>(this->buffer.get()), this->decompressBufferSize - this->istate.avail_out);
} while (this->istate.avail_out == 0);
return boost::system::error_code();
}
boost::system::error_code inflate_reset() {
int ret = inflateReset(&this->istate);
if (ret != Z_OK) {
CCAPI_LOGGER_ERROR("decompress error");
return boost::system::error_code();
}
return boost::system::error_code();
}
#ifndef CCAPI_EXPOSE_INTERNAL
private:
#endif
int windowBits{};
int windowBitsOverride{};
bool initialized{};
std::unique_ptr<unsigned char[]> buffer{nullptr};
z_stream istate;
size_t decompressBufferSize{};
};
} /* namespace ccapi */
#endif // INCLUDE_CCAPI_CPP_CCAPI_INFLATE_STREAM_H_