galaxy 1.0.0
Real-Time C++23 Game Programming Framework. Built on data-driven design principles and agile software engineering.
Loading...
Searching...
No Matches
ZLib.cpp
Go to the documentation of this file.
1
7
10
11#include "ZLib.hpp"
12
13#ifdef GALAXY_WIN_PLATFORM
20#endif
21
22namespace galaxy
23{
24 ZLib::ZLib(const Mode mode)
25 : m_mode {mode}
26 , m_finished {false}
27 , m_in {0}
28 , m_out {0}
29 {
30 try
31 {
33 {
34 m_stream.zalloc = Z_NULL;
35 m_stream.zfree = Z_NULL;
36 m_stream.opaque = Z_NULL;
37
38 if (deflateInit2(&m_stream, 9, Z_DEFLATED, 15, 9, Z_DEFAULT_STRATEGY) != Z_OK)
39 {
40 GALAXY_LOG(GALAXY_ERROR, "Failed to initialize ZLib compressor.");
41 }
42 }
43 else
44 {
45 m_stream.zalloc = Z_NULL;
46 m_stream.zfree = Z_NULL;
47 m_stream.opaque = Z_NULL;
48 m_stream.next_in = Z_NULL;
49 m_stream.avail_in = 0;
50
51 if (inflateInit2(&m_stream, 15) != Z_OK)
52 {
53 GALAXY_LOG(GALAXY_ERROR, "Failed to initialize ZLib decompressor.");
54 }
55 }
56 }
57 catch (const std::exception& e)
58 {
59 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
60 }
61 }
62
64 {
65 try
66 {
68 {
69 deflateEnd(&m_stream);
70 }
71 else
72 {
73 inflateEnd(&m_stream);
74 }
75 }
76 catch (const std::exception& e)
77 {
78 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
79 }
80 }
81
82 std::string ZLib::encode(const std::string& input)
83 {
84 auto in = new char[ZLib::ChunkSize];
85 auto zlib = new ZLib(ZLib::Mode::COMPRESS);
86
87 std::string result;
88
89 try
90 {
91 std::memset(in, 0, sizeof(char) * ZLib::ChunkSize);
92
93 unsigned int total_read = 0;
94
95 std::stringstream sstream;
96 sstream.str(input);
97
98 while (true)
99 {
100 sstream.read(in, ZLib::ChunkSize);
101 total_read = static_cast<unsigned int>(sstream.gcount());
102
103 if (total_read != 0)
104 {
105 result += zlib->compressor({in, total_read});
106 }
107 else
108 {
109 break;
110 }
111 }
112
113 result += zlib->finish();
114 }
115 catch (const std::exception& e)
116 {
117 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
118 }
119
120 delete[] in;
121 delete zlib;
122 return result;
123 }
124
125 std::string ZLib::decode(const std::string& input)
126 {
127 auto in = new char[ZLib::ChunkSize];
128 auto zlib = new ZLib(ZLib::Mode::DECOMPRESS);
129
130 std::string result;
131
132 try
133 {
134 std::memset(in, 0, sizeof(char) * ZLib::ChunkSize);
135
136 unsigned int total_read = 0;
137
138 std::stringstream sstream;
139 sstream.str(input);
140
141 while (true)
142 {
143 sstream.read(in, ZLib::ChunkSize);
144 total_read = static_cast<unsigned int>(sstream.gcount());
145
146 if (total_read != 0)
147 {
148 result += zlib->decompressor({in, total_read});
149 }
150 else
151 {
152 break;
153 }
154 }
155 }
156 catch (const std::exception& e)
157 {
158 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
159 }
160
161 delete[] in;
162 delete zlib;
163 return result;
164 }
165
166 std::string ZLib::compressor(const std::string& input)
167 {
168 std::string result;
169
170 try
171 {
173 {
174 if (!m_finished)
175 {
176 for (auto i = 0u; i < input.length(); i += ZLib::ChunkSize)
177 {
178 const auto left = static_cast<unsigned int>(input.length() - i);
179 const auto end = left <= ZLib::ChunkSize;
180 const auto current = (left > ZLib::ChunkSize) ? ZLib::ChunkSize : left;
181
182 std::memcpy(m_in, input.data() + i, current);
183
184 m_stream.avail_in = current;
185 m_stream.next_in = (Bytef*)m_in;
186
187 do
188 {
189 m_stream.avail_out = ZLib::ChunkSize;
190 m_stream.next_out = (Bytef*)m_out;
191
192 if (deflate(&m_stream, end ? Z_SYNC_FLUSH : Z_NO_FLUSH) == Z_STREAM_ERROR)
193 {
194 GALAXY_LOG(GALAXY_ERROR, "Failed to compress ZLib data stream.");
195 return {};
196 }
197
198 result += std::string(m_out, ZLib::ChunkSize - m_stream.avail_out);
199 } while (m_stream.avail_out == 0);
200 }
201 }
202 else
203 {
204 GALAXY_LOG(GALAXY_WARN, "Dont call ZLib compress after calling zlib finish.");
205 }
206 }
207 else
208 {
209 GALAXY_LOG(GALAXY_WARN, "Dont call ZLib compress in decompression mode.");
210 }
211 }
212 catch (const std::exception& e)
213 {
214 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
215 }
216
217 return result;
218 }
219
220 std::string ZLib::finish()
221 {
222 std::string result;
223
224 try
225 {
227 {
228 if (!m_finished)
229 {
230 m_finished = true;
231 m_stream.avail_in = 0;
232 m_stream.next_in = (Bytef*)m_in;
233
234 do
235 {
236 m_stream.avail_out = ZLib::ChunkSize;
237 m_stream.next_out = (Bytef*)m_out;
238
239 if (deflate(&m_stream, Z_FINISH) == Z_STREAM_ERROR)
240 {
241 GALAXY_LOG(GALAXY_ERROR, "Failed to complete ZLib compression.");
242 return {};
243 }
244
245 result += std::string(m_out, ZLib::ChunkSize - m_stream.avail_out);
246 } while (m_stream.avail_out == 0);
247 }
248 else
249 {
250 GALAXY_LOG(GALAXY_WARN, "ZLib finish already called.");
251 }
252 }
253 else
254 {
255 GALAXY_LOG(GALAXY_WARN, "Dont call ZLib finish in decompress mode.");
256 }
257 }
258 catch (const std::exception& e)
259 {
260 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
261 }
262
263 return result;
264 }
265
266 std::string ZLib::decompressor(const std::string& input)
267 {
268 std::string result;
269
270 try
271 {
273 {
274 for (auto i = 0u; i < input.length(); i += ZLib::ChunkSize)
275 {
276 const auto left = static_cast<unsigned int>(input.length() - i);
277 const auto current = (left > ZLib::ChunkSize) ? ZLib::ChunkSize : left;
278
279 std::memcpy(m_in, input.data() + i, current);
280
281 m_stream.avail_in = current;
282 m_stream.next_in = (Bytef*)m_in;
283
284 if (m_stream.avail_in == 0)
285 {
286 break;
287 }
288 do
289 {
290 m_stream.avail_out = ZLib::ChunkSize;
291 m_stream.next_out = (Bytef*)m_out;
292
293 if (inflate(&m_stream, Z_NO_FLUSH) == Z_STREAM_ERROR)
294 {
295 GALAXY_LOG(GALAXY_ERROR, "Failed to complete ZLib decompression.");
296 return {};
297 }
298
299 result += std::string(m_out, ZLib::ChunkSize - m_stream.avail_out);
300 } while (m_stream.avail_out == 0);
301 }
302 }
303 else
304 {
305 GALAXY_LOG(GALAXY_WARN, "Dont call ZLib finish in compress mode.");
306 }
307 }
308 catch (const std::exception& e)
309 {
310 GALAXY_LOG(GALAXY_ERROR, "{0}.", e.what());
311 }
312
313 return result;
314 }
315} // namespace galaxy
316
317#ifdef GALAXY_WIN_PLATFORM
319#endif
#define GALAXY_LOG(level, msg,...)
Definition Log.hpp:28
#define GALAXY_WARN
Definition Log.hpp:23
#define GALAXY_ERROR
Definition Log.hpp:24
#define GALAXY_DISABLE_WARNING_POP
Definition Pragma.hpp:57
#define GALAXY_DISABLE_WARNING(x)
Definition Pragma.hpp:58
#define GALAXY_DISABLE_WARNING_PUSH
Macro for windows platform detection.
Definition Pragma.hpp:56
char m_out[ZLib::ChunkSize]
Output buffer.
Definition ZLib.hpp:128
~ZLib()
Destructor.
Definition ZLib.cpp:63
static std::string decode(const std::string &input)
Decompresses string into ZLib.
Definition ZLib.cpp:125
std::string finish()
Completes the compression.
Definition ZLib.cpp:220
std::string compressor(const std::string &input)
Compresses string.
Definition ZLib.cpp:166
char m_in[ZLib::ChunkSize]
Input buffer.
Definition ZLib.hpp:123
std::string decompressor(const std::string &input)
Decompresses a zlib string.
Definition ZLib.cpp:266
Mode
ZLib mode to start in.
Definition ZLib.hpp:31
@ COMPRESS
ZLib deflation.
@ DECOMPRESS
ZLib inflation.
z_stream m_stream
Stream object.
Definition ZLib.hpp:113
bool m_finished
Has the compression finished.
Definition ZLib.hpp:118
ZLib(const Mode mode)
Constructor.
Definition ZLib.cpp:24
Mode m_mode
ZLib mode.
Definition ZLib.hpp:108
static std::string encode(const std::string &input)
Compresses string into ZLib.
Definition ZLib.cpp:82
static constexpr const auto ChunkSize
ZLib parsing chunk size.
Definition ZLib.hpp:25
Animated.cpp galaxy.
Definition Animated.cpp:16