mirror of https://github.com/OpenRCT2/OpenRCT2.git
Use actual GZIP compression
This commit is contained in:
parent
341f716c9d
commit
0971db99c3
|
@ -99,16 +99,13 @@ namespace OpenRCT2
|
|||
// Uncompress
|
||||
if (_header.Compression == COMPRESSION_GZIP)
|
||||
{
|
||||
size_t outUncompressedSize{};
|
||||
auto uncompressedData = util_zlib_inflate(
|
||||
reinterpret_cast<const uint8_t*>(_buffer.GetData()), _buffer.GetLength(), &outUncompressedSize);
|
||||
if (_header.UncompressedSize != outUncompressedSize)
|
||||
auto uncompressedData = Ungzip(_buffer.GetData(), _buffer.GetLength());
|
||||
if (_header.UncompressedSize != uncompressedData.size())
|
||||
{
|
||||
// Warning?
|
||||
}
|
||||
_buffer.Clear();
|
||||
_buffer.Write(uncompressedData, outUncompressedSize);
|
||||
std::free(uncompressedData);
|
||||
_buffer.Write(uncompressedData.data(), uncompressedData.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -141,7 +138,7 @@ namespace OpenRCT2
|
|||
std::optional<std::vector<uint8_t>> compressedBytes;
|
||||
if (_header.Compression == COMPRESSION_GZIP)
|
||||
{
|
||||
compressedBytes = util_zlib_deflate(reinterpret_cast<const uint8_t*>(uncompressedData), uncompressedSize);
|
||||
compressedBytes = Gzip(uncompressedData, uncompressedSize);
|
||||
if (compressedBytes)
|
||||
{
|
||||
_header.CompressedSize = compressedBytes->size();
|
||||
|
|
|
@ -696,6 +696,96 @@ bool util_gzip_compress(FILE* source, FILE* dest)
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Gzip(const void* data, size_t dataLen)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
|
||||
std::vector<uint8_t> output;
|
||||
z_stream strm{};
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
auto ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
throw std::runtime_error("deflateInit2 failed with error " + std::to_string(ret));
|
||||
}
|
||||
|
||||
int flush;
|
||||
const auto* src = static_cast<const Bytef*>(data);
|
||||
size_t srcRemaining = dataLen;
|
||||
do
|
||||
{
|
||||
auto nextBlockSize = std::min(srcRemaining, CHUNK);
|
||||
srcRemaining -= nextBlockSize;
|
||||
|
||||
flush = srcRemaining == 0 ? Z_FINISH : Z_NO_FLUSH;
|
||||
strm.avail_in = static_cast<uInt>(nextBlockSize);
|
||||
strm.next_in = const_cast<Bytef*>(src);
|
||||
do
|
||||
{
|
||||
output.resize(output.size() + nextBlockSize);
|
||||
strm.avail_out = nextBlockSize;
|
||||
strm.next_out = &output[output.size() - nextBlockSize];
|
||||
ret = deflate(&strm, flush);
|
||||
if (ret == Z_STREAM_ERROR)
|
||||
{
|
||||
throw std::runtime_error("deflate failed with error " + std::to_string(ret));
|
||||
}
|
||||
output.resize(output.size() - strm.avail_out);
|
||||
} while (strm.avail_out == 0);
|
||||
|
||||
src += nextBlockSize;
|
||||
} while (flush != Z_FINISH);
|
||||
deflateEnd(&strm);
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Ungzip(const void* data, size_t dataLen)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
|
||||
std::vector<uint8_t> output;
|
||||
z_stream strm{};
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
auto ret = inflateInit2(&strm, 15 | 16);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
throw std::runtime_error("inflateInit2 failed with error " + std::to_string(ret));
|
||||
}
|
||||
|
||||
int flush;
|
||||
const auto* src = static_cast<const Bytef*>(data);
|
||||
size_t srcRemaining = dataLen;
|
||||
do
|
||||
{
|
||||
auto nextBlockSize = std::min(srcRemaining, CHUNK);
|
||||
srcRemaining -= nextBlockSize;
|
||||
|
||||
flush = srcRemaining == 0 ? Z_FINISH : Z_NO_FLUSH;
|
||||
strm.avail_in = static_cast<uInt>(nextBlockSize);
|
||||
strm.next_in = const_cast<Bytef*>(src);
|
||||
do
|
||||
{
|
||||
output.resize(output.size() + nextBlockSize);
|
||||
strm.avail_out = nextBlockSize;
|
||||
strm.next_out = &output[output.size() - nextBlockSize];
|
||||
ret = inflate(&strm, flush);
|
||||
if (ret == Z_STREAM_ERROR)
|
||||
{
|
||||
throw std::runtime_error("deflate failed with error " + std::to_string(ret));
|
||||
}
|
||||
output.resize(output.size() - strm.avail_out);
|
||||
} while (strm.avail_out == 0);
|
||||
|
||||
src += nextBlockSize;
|
||||
} while (flush != Z_FINISH);
|
||||
deflateEnd(&strm);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Type-independent code left as macro to reduce duplicate code.
|
||||
#define add_clamp_body(value, value_to_add, min_cap, max_cap) \
|
||||
if ((value_to_add > 0) && (value > (max_cap - (value_to_add)))) \
|
||||
|
|
|
@ -59,6 +59,8 @@ uint32_t util_rand();
|
|||
std::optional<std::vector<uint8_t>> util_zlib_deflate(const uint8_t* data, size_t data_in_size);
|
||||
uint8_t* util_zlib_inflate(const uint8_t* data, size_t data_in_size, size_t* data_out_size);
|
||||
bool util_gzip_compress(FILE* source, FILE* dest);
|
||||
std::vector<uint8_t> Gzip(const void* data, size_t dataLen);
|
||||
std::vector<uint8_t> Ungzip(const void* data, size_t dataLen);
|
||||
|
||||
int8_t add_clamp_int8_t(int8_t value, int8_t value_to_add);
|
||||
int16_t add_clamp_int16_t(int16_t value, int16_t value_to_add);
|
||||
|
@ -71,13 +73,13 @@ uint8_t soft_light(uint8_t a, uint8_t b);
|
|||
|
||||
size_t strcatftime(char* buffer, size_t bufferSize, const char* format, const struct tm* tp);
|
||||
|
||||
template<typename T>[[nodiscard]] constexpr uint64_t EnumToFlag(T v)
|
||||
template<typename T> [[nodiscard]] constexpr uint64_t EnumToFlag(T v)
|
||||
{
|
||||
static_assert(std::is_enum_v<T>);
|
||||
return 1ULL << static_cast<std::underlying_type_t<T>>(v);
|
||||
}
|
||||
|
||||
template<typename... T>[[nodiscard]] constexpr uint64_t EnumsToFlags(T... types)
|
||||
template<typename... T> [[nodiscard]] constexpr uint64_t EnumsToFlags(T... types)
|
||||
{
|
||||
return (EnumToFlag(types) | ...);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue