Files
2026-04-01 19:41:00 +08:00

177 lines
3.3 KiB
C++

#include "memory/dl_memory.h"
#include <cassert>
#include <lz4.h>
#ifndef DL_DISABLE_ZLIB
#include <zlib.h>
#endif
#include "math/dl_algorithm.h"
#include "base/dl_string.h"
namespace dl::Memory
{
Buffer CompressLz4(BufferView src)
{
Buffer ret;
int need_size = LZ4_compressBound((int)src.size());
ret.resize((size_t)need_size);
int ret_size = LZ4_compress_fast(
(const char*)src.data(), (char*)ret.data(),
(int)src.size(), need_size, 1);
if (ret_size <= 0)
{
log_err("压缩失败!");
ret.clear();
}
else
ret.resize((size_t)ret_size);
return ret;
}
Buffer DecompressLz4(BufferView src, size_t size_origin)
{
Buffer ret;
if (size_origin == 0)
{// 未传递原始大小
constexpr size_t K = 4; // 猜测比例
int size_tar;// 解压后大小 -1代表失败
size_origin = src.size();// 缓冲区大小
do
{
size_tar = -1;
size_origin *= K;
ret.resize(size_origin);
size_tar = LZ4_decompress_safe((char*)src.data(), (char*)ret.data(),
(int)src.size(), (int)size_origin);
if (size_tar < 0)
{// 输出区太小,或者编码错误
if (size_origin > src.size() * 1024)
{// 超过原始大小1000倍,我们就认为是编码错误了(似乎没有更好的判断方法)
// 参见https://github.com/lz4/lz4/issues/156
ret.clear();
break;
}
}
else
{
ret.resize(size_tar);
break;
}
} while (true);
}
else
{
ret.resize(size_origin);
int size_tar = LZ4_decompress_safe((char*)src.data(), (char*)ret.data(),
(int)src.size(), (int)size_origin);
if (size_tar != size_origin)
{
log_err("解压失败!");
return {};
}
ret.resize((size_t)size_tar);
}
return ret;
}
#ifndef DL_DISABLE_ZLIB
Buffer CompressZip(BufferView src)
{
Buffer ret;
uLong size_tar = compressBound((uLong)src.size());
ret.resize((size_t)size_tar);
if (compress((Bytef*)ret.data(), &size_tar,
(const Bytef*)src.data(), (uLong)src.size()) != Z_OK)
{
log_err("压缩失败!");
ret.clear();
}
ret.resize(size_tar);
return ret;
}
Buffer DecompressZip(BufferView src, size_t size_origin /*= 0*/)
{
Buffer ret;
if (size_origin == 0)
{// 未传递原始大小
constexpr size_t K = 4; // 猜测比例
uLong size_temp = (uLong)src.size();// 缓冲区大小
do
{
size_temp *= K;
ret.resize(size_temp);
int code = uncompress((Bytef*)ret.data(), &size_temp,
(const Bytef*)src.data(), (uLong)src.size());
if (code == Z_OK)
{
ret.resize(size_temp);
break;
}
else if(code == Z_BUF_ERROR)
{
continue;
}
else if (code == Z_DATA_ERROR)
{
log_err("数据格式错误!");
ret.resize(0);
break;
}
else
{
log_err("解压失败!");
ret.resize(0);
}
} while (true);
}
else
{
ret.resize(size_origin);
uLong size_temp = (uLong)size_origin;
int code = uncompress((Bytef*)ret.data(), &size_temp,
(const Bytef*)src.data(), (uLong)src.size());
if (code == Z_OK)
{
assert(size_temp == (uLong)size_origin);
}
else if (code == Z_BUF_ERROR)
{
log_err("缓冲区不足!");
ret.resize(0);
}
else if (code == Z_DATA_ERROR)
{
log_err("数据格式错误!");
ret.resize(0);
}
else
{
log_err("解压失败!");
ret.resize(0);
}
}
return ret;
}
#endif
#ifndef DL_DISABLE_ZLIB
void TestZip()
{
}
#endif
}