You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
4.2 KiB
C++
106 lines
4.2 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
#include "LZ4Compressor.h"
|
|
|
|
#include <lz4.h>
|
|
#include <lz4hc.h>
|
|
|
|
namespace MultiplayerCompression
|
|
{
|
|
size_t LZ4Compressor::GetMaxChunkSize(size_t maxCompSize) const
|
|
{
|
|
return maxCompSize;
|
|
}
|
|
|
|
size_t LZ4Compressor::GetMaxCompressedBufferSize(size_t uncompSize) const
|
|
{
|
|
return LZ4_compressBound(uncompSize);
|
|
}
|
|
|
|
AzNetworking::CompressorError LZ4Compressor::Compress
|
|
(
|
|
const void* uncompData,
|
|
size_t uncompSize,
|
|
void* compData,
|
|
[[maybe_unused]] size_t compDataSize,
|
|
size_t& compSize
|
|
)
|
|
{
|
|
if (uncompData == nullptr)
|
|
{
|
|
// LZ4 actually never checks for this
|
|
AZ_Warning("Multiplayer Compressor", false, "Input buffer is uninitialized");
|
|
return AzNetworking::CompressorError::Uninitialized;
|
|
}
|
|
|
|
if (compData == nullptr)
|
|
{
|
|
// LZ4 actually never checks for this
|
|
AZ_Warning("Multiplayer Compressor", false, "Output buffer is uninitialized");
|
|
return AzNetworking::CompressorError::Uninitialized;
|
|
}
|
|
|
|
const int compWorstCaseSize = LZ4_compressBound(uncompSize);
|
|
if (compWorstCaseSize == 0)
|
|
{
|
|
AZ_Warning("Multiplayer Compressor", false, "Input size (%lu) passed to Compress() is greater than max allowed (%lu)", uncompSize, LZ4_MAX_INPUT_SIZE);
|
|
return AzNetworking::CompressorError::InsufficientBuffer;
|
|
}
|
|
|
|
AZ_Warning("Multiplayer Compressor", compDataSize >= compWorstCaseSize, "Outbuffer size (%lu B) passed to Compress() is less than estimated worst case (%lu B)", compDataSize, compWorstCaseSize);
|
|
|
|
// Note that this returns a non-negative int so we are narrowing into a size_t here
|
|
compSize = LZ4_compressHC(reinterpret_cast<const char*>(uncompData), reinterpret_cast<char*>(compData), uncompSize);
|
|
|
|
if (compSize == 0)
|
|
{
|
|
// LZ4_compressHC returns a zero value for corrupt data and insufficient buffer
|
|
AZ_Warning("Multiplayer Compressor", false, "Compression failed for uncompSize:(%lu B) compDataSize:(%lu B) compSize:(%lu B)", uncompSize, compDataSize, compSize);
|
|
return AzNetworking::CompressorError::CorruptData;
|
|
}
|
|
|
|
return AzNetworking::CompressorError::Ok;
|
|
}
|
|
|
|
AzNetworking::CompressorError LZ4Compressor::Decompress(const void* compData, size_t compDataSize, void* uncompData, size_t uncompDataSize, size_t& consumedSizeOut, size_t& uncompSizeOut)
|
|
{
|
|
if (uncompData == nullptr)
|
|
{
|
|
// LZ4 actually never checks for this
|
|
AZ_Warning("Multiplayer Compressor", false, "Input buffer is uninitialized");
|
|
return AzNetworking::CompressorError::Uninitialized;
|
|
}
|
|
|
|
if (compData == nullptr)
|
|
{
|
|
// LZ4 actually never checks for this
|
|
AZ_Warning("Multiplayer Compressor", false, "Output buffer is uninitialized");
|
|
return AzNetworking::CompressorError::Uninitialized;
|
|
}
|
|
|
|
const int uncompSize = LZ4_decompress_safe(reinterpret_cast<const char*>(compData), reinterpret_cast<char*>(uncompData), compDataSize, uncompDataSize);
|
|
consumedSizeOut = compDataSize;
|
|
|
|
if (uncompSize < 0)
|
|
{
|
|
// LZ4_decompress_safe returns a negative value for corrupt data and insufficient buffer
|
|
AZ_Warning("Multiplayer Compressor", false, "Decompression failed for compDataSize:(%lu B) uncompDataSize:(%lu B) uncompSize:(%d B)", compDataSize, uncompDataSize, uncompSize);
|
|
return AzNetworking::CompressorError::CorruptData;
|
|
}
|
|
// Assign into the outbound size_t after validating the negative error case
|
|
uncompSizeOut = uncompSize;
|
|
|
|
return AzNetworking::CompressorError::Ok;
|
|
}
|
|
}
|