90 lines
2.2 KiB
C++
90 lines
2.2 KiB
C++
#include "misc/Compression.h"
|
|
|
|
#include <zlib.h>
|
|
#include <cassert>
|
|
|
|
#define COMPRESSION_THRESHOLD 64
|
|
|
|
namespace td {
|
|
namespace utils {
|
|
|
|
unsigned long inflate(const std::string& source, std::string& dest) {
|
|
unsigned long size = dest.size();
|
|
uncompress((Bytef*)&dest[0], &size, (const Bytef*)source.c_str(), source.length());
|
|
return size;
|
|
}
|
|
|
|
unsigned long deflate(const std::string& source, std::string& dest) {
|
|
unsigned long size = source.length();
|
|
dest.resize(size);
|
|
|
|
compress((Bytef*)&dest[0], &size, (const Bytef*)source.c_str(), source.length());
|
|
dest.resize(size);
|
|
return size;
|
|
}
|
|
|
|
DataBuffer Compress(const DataBuffer& buffer) {
|
|
std::string compressedData;
|
|
DataBuffer packet;
|
|
|
|
if (buffer.GetSize() < COMPRESSION_THRESHOLD) {
|
|
// Don't compress since it's a small packet
|
|
std::uint64_t dataLength = 0;
|
|
std::uint64_t packetLength = buffer.GetSize() + sizeof(dataLength);
|
|
|
|
packet << packetLength;
|
|
packet << dataLength;
|
|
packet << buffer;
|
|
return packet;
|
|
}
|
|
|
|
deflate(buffer.ToString(), compressedData);
|
|
|
|
std::uint64_t dataLength = buffer.GetSize();
|
|
std::uint64_t packetLength = compressedData.length() + sizeof(dataLength);
|
|
|
|
packet << packetLength;
|
|
packet << dataLength;
|
|
packet << compressedData;
|
|
return packet;
|
|
}
|
|
|
|
DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength) {
|
|
std::uint64_t uncompressedLength;
|
|
|
|
buffer >> uncompressedLength;
|
|
|
|
std::uint64_t compressedLength = packetLength - sizeof(uncompressedLength);
|
|
|
|
if (uncompressedLength == 0) {
|
|
// Uncompressed
|
|
DataBuffer ret;
|
|
buffer.ReadSome(ret, compressedLength);
|
|
return ret;
|
|
}
|
|
|
|
assert(buffer.GetReadOffset() + compressedLength <= buffer.GetSize());
|
|
|
|
std::string deflatedData;
|
|
buffer.ReadSome(deflatedData, compressedLength);
|
|
|
|
std::string inflated;
|
|
inflated.resize(uncompressedLength);
|
|
|
|
inflate(deflatedData, inflated);
|
|
|
|
assert(inflated.length() == uncompressedLength);
|
|
return DataBuffer(inflated);
|
|
}
|
|
|
|
DataBuffer Decompress(DataBuffer& buffer) {
|
|
std::uint64_t packetLength;
|
|
|
|
buffer >> packetLength;
|
|
|
|
return Decompress(buffer, packetLength);
|
|
}
|
|
|
|
} // namespace utils
|
|
} // namespace td
|