2#include "common/config.h"
26 if (dataSize > LZ4_MAX_INPUT_SIZE)
30 const size_t headersize =
sizeof(uint32_t);
32 int maxdestsize = LZ4_compressBound((
int) dataSize);
33 size_t maxsize = headersize + (size_t) maxdestsize;
34 char *compressedbytes =
nullptr;
38 compressedbytes =
new char[maxsize];
40 catch (std::bad_alloc &)
48 *(uint32_t *) compressedbytes = swapuint32((uint32_t) dataSize);
50 *(uint32_t *) compressedbytes = (uint32_t) dataSize;
56 csize = LZ4_compress_HC(data, compressedbytes + headersize, (
int) dataSize, maxdestsize, LZ4HC_CLEVEL_DEFAULT);
58 csize = LZ4_compress_default(data, compressedbytes + headersize, (
int) dataSize, maxdestsize);
62 delete[] compressedbytes;
69 if ((
double) maxsize / (
double) (csize + headersize) >= 1.2)
71 char *cbytes =
new (std::nothrow)
char[csize + headersize];
74 memcpy(cbytes, compressedbytes, csize + headersize);
75 delete[] compressedbytes;
76 compressedbytes = cbytes;
81 return compressedbytes;
84 char *
decompress(std::string format,
const char *data,
size_t dataSize,
size_t &decompressedSize)
override
89 const size_t headersize =
sizeof(uint32_t);
90 char *rawbytes =
nullptr;
92 if (dataSize < headersize)
98 uint32_t rawsize = swapuint32(*(uint32_t *) data);
100 uint32_t rawsize = *(uint32_t *) data;
105 rawbytes =
new char[rawsize];
107 catch (std::bad_alloc &)
115 if (decompressedSize > 0 && decompressedSize == (
size_t) rawsize)
118 if (LZ4_decompress_fast(data + headersize, rawbytes, (
int) decompressedSize) < 0)
121 throw eve::Exception(
"Could not decompress LZ4-compressed data.");
127 int result = LZ4_decompress_safe(data + headersize, rawbytes,
128 (
int) (dataSize - headersize), rawsize);
133 throw eve::Exception(
"Could not decompress LZ4-compressed data.");
136 decompressedSize = (size_t) result;
144 return format ==
"lz4";
158 uLong zlibCompressBound(std::string format, uLong sourceLen)
160 uLong
size = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13;
163 if (format ==
"gzip")
169 int zlibCompress(std::string format, Bytef *dest, uLongf *destLen,
const Bytef *
source, uLong sourceLen,
int level)
171 z_stream stream = {};
173 stream.next_in = (Bytef *)
source;
174 stream.avail_in = (uInt) sourceLen;
176 stream.next_out = dest;
177 stream.avail_out = (uInt) (*destLen);
180 if (format ==
"gzip")
182 else if (format ==
"deflate")
183 windowbits = -windowbits;
185 int err = deflateInit2(&stream,
level, Z_DEFLATED, windowbits, 8, Z_DEFAULT_STRATEGY);
190 err = deflate(&stream, Z_FINISH);
192 if (err != Z_STREAM_END)
195 return err == Z_OK ? Z_BUF_ERROR : err;
198 *destLen = stream.total_out;
200 return deflateEnd(&stream);
203 int zlibDecompress(std::string format, Bytef *dest, uLongf *destLen,
const Bytef *
source, uLong sourceLen)
205 z_stream stream = {};
207 stream.next_in = (Bytef *)
source;
208 stream.avail_in = (uInt) sourceLen;
210 stream.next_out = dest;
211 stream.avail_out = (uInt) (*destLen);
214 int windowbits = 15 + 32;
216 if (format ==
"deflate")
219 int err = inflateInit2(&stream, windowbits);
224 err = inflate(&stream, Z_FINISH);
226 if (err != Z_STREAM_END)
229 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
234 *destLen = stream.total_out;
236 return inflateEnd(&stream);
247 level = Z_DEFAULT_COMPRESSION;
251 uLong maxsize = zlibCompressBound(format, (uLong) dataSize);
252 char *compressedbytes =
nullptr;
256 compressedbytes =
new char[maxsize];
258 catch (std::bad_alloc &)
263 uLongf destlen = maxsize;
264 int status = zlibCompress(format, (Bytef *) compressedbytes, &destlen, (
const Bytef *) data, (uLong) dataSize,
level);
268 delete[] compressedbytes;
275 if ((
double) maxsize / (
double) destlen >= 1.3)
277 char *cbytes =
new (std::nothrow)
char[destlen];
280 memcpy(cbytes, compressedbytes, destlen);
281 delete[] compressedbytes;
282 compressedbytes = cbytes;
287 return compressedbytes;
290 char *
decompress(std::string format,
const char *data,
size_t dataSize,
size_t &decompressedSize)
override
295 char *rawbytes =
nullptr;
298 size_t rawsize = decompressedSize > 0 ? decompressedSize : dataSize * 2;
305 rawbytes =
new char[rawsize];
307 catch (std::bad_alloc &)
312 uLongf destLen = (uLongf) rawsize;
313 int status = zlibDecompress(format, (Bytef *) rawbytes, &destLen, (
const Bytef *) data, (uLong) dataSize);
317 decompressedSize = (size_t) destLen;
320 else if (
status != Z_BUF_ERROR)
324 throw eve::Exception(
"Could not decompress zlib/gzip-compressed data.");
337 return format ==
"zlib" || format ==
"gzip" || format ==
"deflate";
347 Compressor *compressors[] = {&lz4compressor, &zlibcompressor};
351 if (
c->isSupported(format))
std::uint64_t compressedSize
wgpu::PopErrorScopeStatus status
const UnitySourceAsset & source
EVENGINE_API_FOUNDATION public API.
Base class for backends for different compression formats.
static Compressor * getCompressor(std::string format)
Gets a Compressor that can compress and decompress a specific format. Returns null if there are no su...
char * decompress(std::string format, const char *data, size_t dataSize, size_t &decompressedSize) override
Decompresses compressed data, and returns the decompressed result.
bool isSupported(std::string format) const override
Gets whether a specific format is supported by this backend.
char * compress(std::string format, const char *data, size_t dataSize, int level, size_t &compressedSize) override
Compresses input data, and returns the compressed result.
bool isSupported(std::string format) const override
Gets whether a specific format is supported by this backend.
char * decompress(std::string format, const char *data, size_t dataSize, size_t &decompressedSize) override
Decompresses compressed data, and returns the decompressed result.
char * compress(std::string format, const char *data, size_t dataSize, int level, size_t &compressedSize) override
Compresses input data, and returns the compressed result.
Build metadata (engine git commit, build time, third-party version).