CppUtils/zlib_cpp/ZlibCompressor.cpp
2025-06-05 10:06:43 +08:00

165 lines
5.6 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ZlibCompressor.h"
#include <algorithm>
namespace ZlibCpp {
ZlibCompressor::ZlibCompressor(CompressionLevel level, DataFormat format, CompressionStrategy strategy)
: level_(level), format_(format), strategy_(strategy), finished_(false) {
Initialize(level, format, strategy);
}
ZlibCompressor::~ZlibCompressor() { if (initialized_) { Cleanup(); } }
void ZlibCompressor::Initialize(CompressionLevel level, DataFormat format, CompressionStrategy strategy) {
if (initialized_) {
Cleanup();
}
level_ = level;
format_ = format;
strategy_ = strategy;
finished_ = false;
// 计算窗口位数
int windowBits = 15; // 默认窗口大小
if (format == DataFormat::Gzip) {
windowBits += 16; // Gzip格式
} else if (format == DataFormat::Raw) {
windowBits = -windowBits; // 原始deflate格式
}
int result = deflateInit2(&stream_,
static_cast<int>(level),
Z_DEFLATED,
windowBits,
8, // memLevel
static_cast<int>(strategy));
CheckResult(result, "deflateInit2");
initialized_ = true;
}
void ZlibCompressor::Reset() {
if (!initialized_) {
throw ZlibStreamException("压缩器未初始化");
}
int result = deflateReset(&stream_);
CheckResult(result, "deflateReset");
finished_ = false;
}
std::vector<uint8_t> ZlibCompressor::Compress(const std::vector<uint8_t>& input, bool flush) {
return Compress(input.data(), input.size(), flush);
}
std::vector<uint8_t> ZlibCompressor::Compress(const uint8_t* input, size_t input_size, bool flush) {
if (finished_) {
throw ZlibStreamException("压缩器已完成,无法继续压缩");
}
int flush_mode = flush ? Z_SYNC_FLUSH : Z_NO_FLUSH;
return CompressInternal(input, input_size, flush_mode);
}
std::vector<uint8_t> ZlibCompressor::Finish() {
if (finished_) {
return {};
}
finished_ = true;
return CompressInternal(nullptr, 0, Z_FINISH);
}
std::vector<uint8_t> ZlibCompressor::CompressInternal(const uint8_t* input, size_t input_size, int flush_mode) {
if (!initialized_) {
throw ZlibStreamException("压缩器未初始化");
}
std::vector<uint8_t> output;
const size_t buffer_size = 8192; // 8KB缓冲区
uint8_t buffer[buffer_size];
stream_.next_in = const_cast<Bytef*>(input);
stream_.avail_in = static_cast<uInt>(input_size);
do {
stream_.next_out = buffer;
stream_.avail_out = buffer_size;
int result = deflate(&stream_, flush_mode);
if (result != Z_OK && result != Z_STREAM_END && result != Z_BUF_ERROR) {
CheckResult(result, "deflate");
}
size_t produced = buffer_size - stream_.avail_out;
if (produced > 0) {
size_t old_size = output.size();
output.resize(old_size + produced);
std::copy(buffer, buffer + produced, output.begin() + old_size);
}
// 如果是Z_FINISH且返回Z_STREAM_END表示压缩完成
if (flush_mode == Z_FINISH && result == Z_STREAM_END) {
break;
}
} while (stream_.avail_out == 0); // 当输出缓冲区被填满时继续
return output;
}
std::vector<uint8_t> ZlibCompressor::CompressData(const std::vector<uint8_t>& input,
CompressionLevel level,
DataFormat format) {
ZlibCompressor compressor(level, format);
auto result = compressor.Compress(input);
auto final = compressor.Finish();
result.insert(result.end(), final.begin(), final.end());
return result;
}
std::vector<uint8_t> ZlibCompressor::CompressString(const std::string& input,
CompressionLevel level,
DataFormat format) {
std::vector<uint8_t> data(input.begin(), input.end());
return CompressData(data, level, format);
}
void ZlibCompressor::SetDictionary(const std::vector<uint8_t>& dictionary) {
if (!initialized_) {
throw ZlibStreamException("压缩器未初始化");
}
int result = deflateSetDictionary(&stream_, dictionary.data(),
static_cast<uInt>(dictionary.size()));
CheckResult(result, "deflateSetDictionary");
}
void ZlibCompressor::GetParams(CompressionLevel& level, CompressionStrategy& strategy) const {
level = level_;
strategy = strategy_;
}
void ZlibCompressor::SetParams(CompressionLevel level, CompressionStrategy strategy) {
if (!initialized_) {
throw ZlibStreamException("压缩器未初始化");
}
int result = deflateParams(&stream_, static_cast<int>(level), static_cast<int>(strategy));
CheckResult(result, "deflateParams");
level_ = level;
strategy_ = strategy;
}
void ZlibCompressor::Cleanup() {
if (initialized_) {
deflateEnd(&stream_);
initialized_ = false;
}
}
} // namespace ZlibCpp