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