mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 19:13:07 +01:00
Move Compression from Util into its own compilation unit
This commit is contained in:
176
src/openrct2/core/Compression.cpp
Normal file
176
src/openrct2/core/Compression.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2024 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Compression.h"
|
||||
|
||||
#include "../Diagnostic.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace OpenRCT2::Compression
|
||||
{
|
||||
constexpr size_t CHUNK = 128 * 1024;
|
||||
|
||||
// Compress the source to gzip-compatible stream, write to dest.
|
||||
// Mainly used for compressing the crashdumps
|
||||
bool gzipCompress(FILE* source, FILE* dest)
|
||||
{
|
||||
if (source == nullptr || dest == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int ret, flush;
|
||||
size_t have;
|
||||
z_stream strm{};
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
unsigned char in[CHUNK];
|
||||
unsigned char out[CHUNK];
|
||||
int windowBits = 15;
|
||||
int GZIP_ENCODING = 16;
|
||||
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
LOG_ERROR("Failed to initialise stream");
|
||||
return false;
|
||||
}
|
||||
do
|
||||
{
|
||||
strm.avail_in = uInt(fread(in, 1, CHUNK, source));
|
||||
if (ferror(source))
|
||||
{
|
||||
deflateEnd(&strm);
|
||||
LOG_ERROR("Failed to read data from source");
|
||||
return false;
|
||||
}
|
||||
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
|
||||
strm.next_in = in;
|
||||
do
|
||||
{
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = out;
|
||||
ret = deflate(&strm, flush);
|
||||
if (ret == Z_STREAM_ERROR)
|
||||
{
|
||||
LOG_ERROR("Failed to compress data");
|
||||
return false;
|
||||
}
|
||||
have = CHUNK - strm.avail_out;
|
||||
if (fwrite(out, 1, have, dest) != have || ferror(dest))
|
||||
{
|
||||
deflateEnd(&strm);
|
||||
LOG_ERROR("Failed to write data to destination");
|
||||
return false;
|
||||
}
|
||||
} while (strm.avail_out == 0);
|
||||
} while (flush != Z_FINISH);
|
||||
deflateEnd(&strm);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> gzip(const void* data, const 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;
|
||||
|
||||
{
|
||||
const 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 = 0;
|
||||
const auto* src = static_cast<const Bytef*>(data);
|
||||
size_t srcRemaining = dataLen;
|
||||
do
|
||||
{
|
||||
const 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 = static_cast<uInt>(nextBlockSize);
|
||||
strm.next_out = &output[output.size() - nextBlockSize];
|
||||
const auto 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, const 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;
|
||||
|
||||
{
|
||||
const auto ret = inflateInit2(&strm, 15 | 16);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
throw std::runtime_error("inflateInit2 failed with error " + std::to_string(ret));
|
||||
}
|
||||
}
|
||||
|
||||
int flush = 0;
|
||||
const auto* src = static_cast<const Bytef*>(data);
|
||||
size_t srcRemaining = dataLen;
|
||||
do
|
||||
{
|
||||
const 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 = static_cast<uInt>(nextBlockSize);
|
||||
strm.next_out = &output[output.size() - nextBlockSize];
|
||||
const auto 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);
|
||||
inflateEnd(&strm);
|
||||
return output;
|
||||
}
|
||||
} // namespace OpenRCT2::Compression
|
||||
21
src/openrct2/core/Compression.h
Normal file
21
src/openrct2/core/Compression.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2024 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenRCT2::Compression
|
||||
{
|
||||
bool gzipCompress(FILE* source, FILE* dest);
|
||||
std::vector<uint8_t> gzip(const void* data, const size_t dataLen);
|
||||
std::vector<uint8_t> ungzip(const void* data, const size_t dataLen);
|
||||
} // namespace OpenRCT2::Compression
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/Util.h"
|
||||
#include "../core/Compression.h"
|
||||
#include "../world/Location.hpp"
|
||||
#include "Crypt.h"
|
||||
#include "FileStream.h"
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <stack>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
@@ -99,7 +100,7 @@ namespace OpenRCT2
|
||||
// Uncompress
|
||||
if (_header.Compression == COMPRESSION_GZIP)
|
||||
{
|
||||
auto uncompressedData = Ungzip(_buffer.GetData(), _buffer.GetLength());
|
||||
auto uncompressedData = Compression::ungzip(_buffer.GetData(), _buffer.GetLength());
|
||||
if (_header.UncompressedSize != uncompressedData.size())
|
||||
{
|
||||
// Warning?
|
||||
@@ -135,7 +136,7 @@ namespace OpenRCT2
|
||||
std::optional<std::vector<uint8_t>> compressedBytes;
|
||||
if (_header.Compression == COMPRESSION_GZIP)
|
||||
{
|
||||
compressedBytes = Gzip(uncompressedData, uncompressedSize);
|
||||
compressedBytes = Compression::gzip(uncompressedData, uncompressedSize);
|
||||
if (compressedBytes)
|
||||
{
|
||||
_header.CompressedSize = compressedBytes->size();
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
<ClInclude Include="core\CircularBuffer.h" />
|
||||
<ClInclude Include="core\CodepointView.hpp" />
|
||||
<ClInclude Include="core\Collections.hpp" />
|
||||
<ClInclude Include="core\Compression.h" />
|
||||
<ClInclude Include="core\Console.hpp" />
|
||||
<ClInclude Include="core\Crypt.h" />
|
||||
<ClInclude Include="core\DataSerialiser.h" />
|
||||
@@ -745,6 +746,7 @@
|
||||
<ClCompile Include="config\IniWriter.cpp" />
|
||||
<ClCompile Include="Context.cpp" />
|
||||
<ClCompile Include="core\ChecksumStream.cpp" />
|
||||
<ClCompile Include="core\Compression.cpp" />
|
||||
<ClCompile Include="core\Console.cpp" />
|
||||
<ClCompile Include="core\Crypt.CNG.cpp" />
|
||||
<ClCompile Include="core\Crypt.OpenRCT2.cpp" />
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
# include "../PlatformEnvironment.h"
|
||||
# include "../Version.h"
|
||||
# include "../config/Config.h"
|
||||
# include "../core/Compression.h"
|
||||
# include "../core/Console.hpp"
|
||||
# include "../core/Guard.hpp"
|
||||
# include "../core/Path.hpp"
|
||||
@@ -139,7 +140,7 @@ static bool OnCrash(
|
||||
FILE* input = _wfopen(dumpFilePath, L"rb");
|
||||
FILE* dest = _wfopen(dumpFilePathGZIP, L"wb");
|
||||
|
||||
if (UtilGzipCompress(input, dest))
|
||||
if (Compression::gzipCompress(input, dest))
|
||||
{
|
||||
// TODO: enable upload of gzip-compressed dumps once supported on
|
||||
// backtrace.io (uncomment the line below). For now leave compression
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "../interface/Window.h"
|
||||
#include "../platform/Platform.h"
|
||||
#include "../scenes/title/TitleScene.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -225,162 +224,6 @@ float UtilRandNormalDistributed()
|
||||
return _distributor(_prng);
|
||||
}
|
||||
|
||||
constexpr size_t CHUNK = 128 * 1024;
|
||||
|
||||
// Compress the source to gzip-compatible stream, write to dest.
|
||||
// Mainly used for compressing the crashdumps
|
||||
bool UtilGzipCompress(FILE* source, FILE* dest)
|
||||
{
|
||||
if (source == nullptr || dest == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int ret, flush;
|
||||
size_t have;
|
||||
z_stream strm{};
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
unsigned char in[CHUNK];
|
||||
unsigned char out[CHUNK];
|
||||
int windowBits = 15;
|
||||
int GZIP_ENCODING = 16;
|
||||
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
LOG_ERROR("Failed to initialise stream");
|
||||
return false;
|
||||
}
|
||||
do
|
||||
{
|
||||
strm.avail_in = uInt(fread(in, 1, CHUNK, source));
|
||||
if (ferror(source))
|
||||
{
|
||||
deflateEnd(&strm);
|
||||
LOG_ERROR("Failed to read data from source");
|
||||
return false;
|
||||
}
|
||||
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
|
||||
strm.next_in = in;
|
||||
do
|
||||
{
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = out;
|
||||
ret = deflate(&strm, flush);
|
||||
if (ret == Z_STREAM_ERROR)
|
||||
{
|
||||
LOG_ERROR("Failed to compress data");
|
||||
return false;
|
||||
}
|
||||
have = CHUNK - strm.avail_out;
|
||||
if (fwrite(out, 1, have, dest) != have || ferror(dest))
|
||||
{
|
||||
deflateEnd(&strm);
|
||||
LOG_ERROR("Failed to write data to destination");
|
||||
return false;
|
||||
}
|
||||
} while (strm.avail_out == 0);
|
||||
} while (flush != Z_FINISH);
|
||||
deflateEnd(&strm);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Gzip(const void* data, const 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;
|
||||
|
||||
{
|
||||
const 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 = 0;
|
||||
const auto* src = static_cast<const Bytef*>(data);
|
||||
size_t srcRemaining = dataLen;
|
||||
do
|
||||
{
|
||||
const 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 = static_cast<uInt>(nextBlockSize);
|
||||
strm.next_out = &output[output.size() - nextBlockSize];
|
||||
const auto 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, const 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;
|
||||
|
||||
{
|
||||
const auto ret = inflateInit2(&strm, 15 | 16);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
throw std::runtime_error("inflateInit2 failed with error " + std::to_string(ret));
|
||||
}
|
||||
}
|
||||
|
||||
int flush = 0;
|
||||
const auto* src = static_cast<const Bytef*>(data);
|
||||
size_t srcRemaining = dataLen;
|
||||
do
|
||||
{
|
||||
const 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 = static_cast<uInt>(nextBlockSize);
|
||||
strm.next_out = &output[output.size() - nextBlockSize];
|
||||
const auto 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);
|
||||
inflateEnd(&strm);
|
||||
return output;
|
||||
}
|
||||
|
||||
uint8_t Lerp(uint8_t a, uint8_t b, float t)
|
||||
{
|
||||
if (t <= 0)
|
||||
|
||||
@@ -38,10 +38,6 @@ char* SafeStrCat(char* destination, const char* source, size_t size);
|
||||
uint32_t UtilRand();
|
||||
float UtilRandNormalDistributed();
|
||||
|
||||
bool UtilGzipCompress(FILE* source, FILE* dest);
|
||||
std::vector<uint8_t> Gzip(const void* data, const size_t dataLen);
|
||||
std::vector<uint8_t> Ungzip(const void* data, const size_t dataLen);
|
||||
|
||||
template<typename T>
|
||||
constexpr T AddClamp(T value, T valueToAdd)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user