mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-17 03:53:07 +01:00
Remove chunk code from SawyerEncoding
This commit is contained in:
@@ -14,171 +14,52 @@
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include <memory>
|
||||
#include "../core/IStream.hpp"
|
||||
#include "../core/Math.hpp"
|
||||
#include "SawyerEncoding.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../util/sawyercoding.h"
|
||||
}
|
||||
|
||||
namespace SawyerEncoding
|
||||
{
|
||||
void SkipChunk(IStream * stream)
|
||||
{
|
||||
auto header = stream->ReadValue<sawyercoding_chunk_header>();
|
||||
stream->Seek(header.length, STREAM_SEEK_CURRENT);
|
||||
}
|
||||
|
||||
void * ReadChunk(IStream * stream, size_t * outSize)
|
||||
{
|
||||
uint64 originalPosition = stream->GetPosition();
|
||||
|
||||
auto header = stream->ReadValue<sawyercoding_chunk_header>();
|
||||
switch (header.encoding) {
|
||||
case CHUNK_ENCODING_NONE:
|
||||
case CHUNK_ENCODING_RLE:
|
||||
case CHUNK_ENCODING_RLECOMPRESSED:
|
||||
case CHUNK_ENCODING_ROTATE:
|
||||
{
|
||||
std::unique_ptr<uint8> compressedData = std::unique_ptr<uint8>(Memory::Allocate<uint8>(header.length));
|
||||
if (stream->TryRead(compressedData.get(), header.length) != header.length)
|
||||
{
|
||||
throw IOException("Corrupt chunk size.");
|
||||
}
|
||||
|
||||
// Allow 16MiB for chunk data
|
||||
size_t bufferSize = 16 * 1024 * 1024;
|
||||
uint8 * buffer = Memory::Allocate<uint8>(bufferSize);
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
throw Exception("Unable to allocate buffer.");
|
||||
}
|
||||
|
||||
size_t uncompressedLength = sawyercoding_read_chunk_buffer(buffer, compressedData.get(), header, bufferSize);
|
||||
buffer = Memory::Reallocate(buffer, uncompressedLength);
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
throw Exception("Unable to reallocate buffer.");
|
||||
}
|
||||
|
||||
if (outSize != nullptr) *outSize = uncompressedLength;
|
||||
return buffer;
|
||||
}
|
||||
default:
|
||||
stream->SetPosition(originalPosition);
|
||||
throw IOException("Invalid chunk encoding.");
|
||||
}
|
||||
}
|
||||
|
||||
void ReadChunk(void * dst, size_t expectedSize, IStream * stream)
|
||||
{
|
||||
if (!TryReadChunk(dst, expectedSize, stream))
|
||||
{
|
||||
throw IOException("Invalid or incorrect chunk size.");
|
||||
}
|
||||
}
|
||||
|
||||
void ReadChunkTolerant(void * dst, size_t expectedSize, IStream * stream)
|
||||
{
|
||||
uint64 originalPosition = stream->GetPosition();
|
||||
|
||||
auto header = stream->ReadValue<sawyercoding_chunk_header>();
|
||||
switch (header.encoding) {
|
||||
case CHUNK_ENCODING_NONE:
|
||||
case CHUNK_ENCODING_RLE:
|
||||
case CHUNK_ENCODING_RLECOMPRESSED:
|
||||
case CHUNK_ENCODING_ROTATE:
|
||||
{
|
||||
std::unique_ptr<uint8> compressedData = std::unique_ptr<uint8>(Memory::Allocate<uint8>(header.length));
|
||||
if (stream->TryRead(compressedData.get(), header.length) != header.length)
|
||||
{
|
||||
throw IOException("Corrupt chunk size.");
|
||||
}
|
||||
|
||||
// Allow 16MiB for chunk data
|
||||
size_t bufferSize = 16 * 1024 * 1024;
|
||||
std::unique_ptr<uint8> buffer = std::unique_ptr<uint8>(Memory::Allocate<uint8>(bufferSize));
|
||||
size_t uncompressedLength = sawyercoding_read_chunk_buffer(buffer.get(), compressedData.get(), header, bufferSize);
|
||||
size_t copyLength = Math::Min(uncompressedLength, expectedSize);
|
||||
|
||||
Memory::Set(dst, 0, expectedSize);
|
||||
Memory::Copy<void>(dst, buffer.get(), copyLength);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
stream->SetPosition(originalPosition);
|
||||
throw IOException("Invalid chunk encoding.");
|
||||
}
|
||||
}
|
||||
|
||||
bool TryReadChunk(void * dst, size_t expectedSize, IStream * stream)
|
||||
{
|
||||
uint64 originalPosition = stream->GetPosition();
|
||||
|
||||
bool success = false;
|
||||
auto header = stream->ReadValue<sawyercoding_chunk_header>();
|
||||
switch (header.encoding) {
|
||||
case CHUNK_ENCODING_NONE:
|
||||
case CHUNK_ENCODING_RLE:
|
||||
case CHUNK_ENCODING_RLECOMPRESSED:
|
||||
case CHUNK_ENCODING_ROTATE:
|
||||
uint8 * compressedData = Memory::Allocate<uint8>(header.length);
|
||||
if (stream->TryRead(compressedData, header.length) == header.length)
|
||||
{
|
||||
size_t uncompressedLength = sawyercoding_read_chunk_buffer((uint8 *)dst, compressedData, header, expectedSize);
|
||||
if (uncompressedLength == expectedSize)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
Memory::Free(compressedData);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
stream->SetPosition(originalPosition);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ValidateChecksum(IStream * stream)
|
||||
{
|
||||
// Get data size
|
||||
uint64 initialPosition = stream->GetPosition();
|
||||
uint64 dataSize = stream->GetLength() - initialPosition;
|
||||
if (dataSize < 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
dataSize -= 4;
|
||||
|
||||
// Calculate checksum
|
||||
uint32 checksum = 0;
|
||||
do
|
||||
try
|
||||
{
|
||||
uint8 buffer[4096];
|
||||
uint64 bufferSize = Math::Min<uint64>(dataSize, sizeof(buffer));
|
||||
stream->Read(buffer, bufferSize);
|
||||
|
||||
for (uint64 i = 0; i < bufferSize; i++)
|
||||
// Calculate checksum
|
||||
uint32 checksum = 0;
|
||||
do
|
||||
{
|
||||
checksum += buffer[i];
|
||||
uint8 buffer[4096];
|
||||
uint64 bufferSize = Math::Min<uint64>(dataSize, sizeof(buffer));
|
||||
stream->Read(buffer, bufferSize);
|
||||
|
||||
for (uint64 i = 0; i < bufferSize; i++)
|
||||
{
|
||||
checksum += buffer[i];
|
||||
}
|
||||
|
||||
dataSize -= bufferSize;
|
||||
}
|
||||
while (dataSize != 0);
|
||||
|
||||
dataSize -= bufferSize;
|
||||
// Read file checksum
|
||||
uint32 fileChecksum = stream->ReadValue<uint32>();
|
||||
|
||||
// Rewind back to original position
|
||||
stream->SetPosition(initialPosition);
|
||||
return checksum == fileChecksum;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Rewind back to original position
|
||||
stream->SetPosition(initialPosition);
|
||||
return false;
|
||||
}
|
||||
while (dataSize != 0);
|
||||
|
||||
// Read file checksum
|
||||
uint32 fileChecksum = stream->ReadValue<uint32>();
|
||||
|
||||
// Rewind
|
||||
stream->SetPosition(initialPosition);
|
||||
|
||||
return checksum == fileChecksum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,17 +22,5 @@ interface IStream;
|
||||
|
||||
namespace SawyerEncoding
|
||||
{
|
||||
void SkipChunk(IStream * stream);
|
||||
void * ReadChunk(IStream * stream, size_t * outSize);
|
||||
void ReadChunk(void * dst, size_t expectedSize, IStream * stream);
|
||||
void ReadChunkTolerant(void * dst, size_t expectedSize, IStream * stream);
|
||||
bool TryReadChunk(void * dst, size_t expectedSize, IStream * stream);
|
||||
|
||||
template<typename T>
|
||||
bool TryReadChunk(T * dst, IStream * stream)
|
||||
{
|
||||
return TryReadChunk(dst, sizeof(T), stream);
|
||||
}
|
||||
|
||||
bool ValidateChecksum(IStream * stream);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user