#include "memory/dl_memory.h" #include #include #ifndef DL_DISABLE_ZLIB #include #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 }