177 lines
3.3 KiB
C++
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
|
|
|
|
|
|
} |