1
+ #pragma once
2
+ #include " generic_compression.h"
3
+ #include " zlib-ng/zlib-ng.h"
4
+ #include < array>
5
+ #include < queue>
6
+
7
+ namespace SleepyDiscord {
8
+ class ZLibCompression : public GenericCompression {
9
+ public:
10
+ bool uncompress (const std::string& compressed, std::string& uncompressedOut) override {
11
+ auto stream = zng_stream{};
12
+ memset (&stream, 0 , sizeof (stream));
13
+ int output = zng_inflateInit (&stream);
14
+ if (output != Z_OK) {
15
+ zng_inflateEnd (&stream);
16
+ return false ;
17
+ }
18
+
19
+ stream.next_in = reinterpret_cast <const uint8_t *>(compressed.data ());
20
+ stream.avail_in = static_cast <uint32_t >(compressed.length ());
21
+
22
+ constexpr size_t chunkSize = 16 * 1024 ;
23
+ using Data = std::array<char , chunkSize>;
24
+ using Buffer = std::pair<Data, std::size_t >;
25
+ std::list<Buffer> outputQueue;
26
+
27
+ bool makeNewBuffer = true ;
28
+ std::size_t totalSize = 0 ;
29
+ output = Z_BUF_ERROR;
30
+ do {
31
+ if (makeNewBuffer == true ) {
32
+ outputQueue.emplace_back (); // make a new output buffer
33
+ makeNewBuffer = false ;
34
+ }
35
+ Buffer& buffer = outputQueue.back ();
36
+ Data& data = buffer.first ;
37
+ std::size_t size = buffer.second ;
38
+
39
+ stream.next_out = reinterpret_cast <uint8_t *>(&data[size]);
40
+ stream.avail_out = static_cast <uint32_t >(data.max_size () - size);
41
+
42
+ output = zng_inflate (&stream, Z_SYNC_FLUSH);
43
+
44
+ auto oldSize = size;
45
+ size = data.max_size () - stream.avail_out ;
46
+ buffer.second = size;
47
+ auto deltaSize = size - oldSize;
48
+ totalSize += deltaSize;
49
+
50
+ if (output == Z_STREAM_END) {
51
+ output = zng_inflateEnd (&stream);
52
+ break ;
53
+ } else if (deltaSize == 0 ) {
54
+ makeNewBuffer = true ;
55
+ }
56
+ } while (output == Z_OK || output == Z_BUF_ERROR);
57
+
58
+ uncompressedOut.clear ();
59
+ uncompressedOut.reserve (totalSize);
60
+ for (; 0 < outputQueue.size (); outputQueue.pop_front ()) {
61
+ Buffer& buffer = outputQueue.front ();
62
+ Data& data = buffer.first ;
63
+ std::size_t size = buffer.second ;
64
+
65
+ uncompressedOut.append (data.data (), size);
66
+ }
67
+
68
+ return true ;
69
+ }
70
+ };
71
+
72
+ using DefaultCompression = ZLibCompression;
73
+ #define SLEEPY_DEFAULT_COMPRESSION ZLibCompression
74
+ }
0 commit comments