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