#include #include #include #include namespace sp { namespace zlib { static DataBuffer Inflate(const std::uint8_t* source, std::size_t size, std::size_t uncompressedSize) { DataBuffer result; result.Resize(uncompressedSize); uncompress(static_cast(result.data()), reinterpret_cast(&uncompressedSize), static_cast(source), static_cast(size)); assert(result.GetSize() == uncompressedSize); return result; } static DataBuffer Deflate(const std::uint8_t* source, std::size_t size) { DataBuffer result; uLongf compressedSize = size; result.Resize(size); // Resize for the compressed data to fit into compress(static_cast(result.data()), &compressedSize, static_cast(source), static_cast(size)); result.Resize(compressedSize); // Resize to cut useless data return result; } DataBuffer Compress(const DataBuffer& buffer, std::size_t a_CompressionThreshold) { DataBuffer packet; if (buffer.GetSize() < a_CompressionThreshold) { // Don't compress since it's a small packet packet << VarInt{0}; packet << buffer; return packet; } DataBuffer compressedData = Deflate(buffer.data(), buffer.GetSize()); VarInt uncompressedDataLength = buffer.GetSize(); if (compressedData.GetSize() >= buffer.GetSize()) { // the compression is overkill so we don't send the compressed buffer packet << VarInt{0}; packet << buffer; } else { packet << uncompressedDataLength; packet << compressedData; } return packet; } DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength) { VarInt uncompressedLength; buffer >> uncompressedLength; std::uint64_t compressedLength = packetLength - uncompressedLength.GetSerializedLength(); if (uncompressedLength.GetValue() == 0) { // Data already uncompressed. Nothing to do DataBuffer ret; buffer.ReadSome(ret, compressedLength); return ret; } assert(buffer.GetReadOffset() + compressedLength <= buffer.GetSize()); return Inflate(buffer.data() + buffer.GetReadOffset(), compressedLength, uncompressedLength.GetValue()); } } // namespace zlib DataBuffer ZlibCompress::EncapsulateImpl(const DataBuffer& a_Data) { return zlib::Compress(a_Data, m_CompressionThreshold); } DataBuffer ZlibCompress::DecapsulateImpl(DataBuffer& a_Data) { return zlib::Decompress(a_Data, a_Data.GetSize()); } } // namespace sp