150 lines
4.7 KiB
C++
150 lines
4.7 KiB
C++
|
#include "ZlibDecompressor.h"
|
|||
|
#include <algorithm>
|
|||
|
|
|||
|
namespace ZlibCpp {
|
|||
|
|
|||
|
ZlibDecompressor::ZlibDecompressor(DataFormat format)
|
|||
|
: format_(format), finished_(false) {
|
|||
|
Initialize(format);
|
|||
|
}
|
|||
|
|
|||
|
ZlibDecompressor::~ZlibDecompressor() { if (initialized_) { Cleanup(); } }
|
|||
|
|
|||
|
void ZlibDecompressor::Initialize(DataFormat format) {
|
|||
|
if (initialized_) {
|
|||
|
Cleanup();
|
|||
|
}
|
|||
|
|
|||
|
format_ = format;
|
|||
|
finished_ = false;
|
|||
|
|
|||
|
// 计算窗口位数
|
|||
|
int windowBits = 15; // 默认窗口大小
|
|||
|
if (format == DataFormat::Gzip) {
|
|||
|
windowBits += 16; // Gzip格式
|
|||
|
} else if (format == DataFormat::Raw) {
|
|||
|
windowBits = -windowBits; // 原始deflate格式
|
|||
|
}
|
|||
|
|
|||
|
int result = inflateInit2(&stream_, windowBits);
|
|||
|
CheckResult(result, "inflateInit2");
|
|||
|
initialized_ = true;
|
|||
|
}
|
|||
|
|
|||
|
void ZlibDecompressor::Reset() {
|
|||
|
if (!initialized_) {
|
|||
|
throw ZlibStreamException("解压缩器未初始化");
|
|||
|
}
|
|||
|
|
|||
|
int result = inflateReset(&stream_);
|
|||
|
CheckResult(result, "inflateReset");
|
|||
|
finished_ = false;
|
|||
|
}
|
|||
|
|
|||
|
std::vector<uint8_t> ZlibDecompressor::Decompress(const std::vector<uint8_t>& input, bool flush) {
|
|||
|
return Decompress(input.data(), input.size(), flush);
|
|||
|
}
|
|||
|
|
|||
|
std::vector<uint8_t> ZlibDecompressor::Decompress(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 DecompressInternal(input, input_size, flush_mode);
|
|||
|
}
|
|||
|
|
|||
|
std::vector<uint8_t> ZlibDecompressor::Finish() {
|
|||
|
if (finished_) {
|
|||
|
return {};
|
|||
|
}
|
|||
|
|
|||
|
finished_ = true;
|
|||
|
return DecompressInternal(nullptr, 0, Z_FINISH);
|
|||
|
}
|
|||
|
|
|||
|
std::vector<uint8_t> ZlibDecompressor::DecompressInternal(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 = inflate(&stream_, flush_mode);
|
|||
|
|
|||
|
// 处理需要字典的情况
|
|||
|
if (result == Z_NEED_DICT) {
|
|||
|
throw ZlibDataException("需要字典进行解压缩");
|
|||
|
}
|
|||
|
|
|||
|
if (result != Z_OK && result != Z_STREAM_END && result != Z_BUF_ERROR) {
|
|||
|
CheckResult(result, "inflate");
|
|||
|
}
|
|||
|
|
|||
|
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_STREAM_END,表示解压缩完成
|
|||
|
if (result == Z_STREAM_END) {
|
|||
|
finished_ = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
} while (stream_.avail_out == 0); // 当输出缓冲区被填满时继续
|
|||
|
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
std::vector<uint8_t> ZlibDecompressor::DecompressData(const std::vector<uint8_t>& input, DataFormat format) {
|
|||
|
ZlibDecompressor decompressor(format);
|
|||
|
auto result = decompressor.Decompress(input);
|
|||
|
auto final = decompressor.Finish();
|
|||
|
|
|||
|
result.insert(result.end(), final.begin(), final.end());
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
std::string ZlibDecompressor::DecompressString(const std::vector<uint8_t>& input, DataFormat format) {
|
|||
|
auto data = DecompressData(input, format);
|
|||
|
return std::string(data.begin(), data.end());
|
|||
|
}
|
|||
|
|
|||
|
void ZlibDecompressor::SetDictionary(const std::vector<uint8_t>& dictionary) {
|
|||
|
if (!initialized_) {
|
|||
|
throw ZlibStreamException("解压缩器未初始化");
|
|||
|
}
|
|||
|
|
|||
|
int result = inflateSetDictionary(&stream_, dictionary.data(),
|
|||
|
static_cast<uInt>(dictionary.size()));
|
|||
|
CheckResult(result, "inflateSetDictionary");
|
|||
|
}
|
|||
|
|
|||
|
bool ZlibDecompressor::IsFinished() const {
|
|||
|
return finished_;
|
|||
|
}
|
|||
|
|
|||
|
DataFormat ZlibDecompressor::GetFormat() const {
|
|||
|
return format_;
|
|||
|
}
|
|||
|
|
|||
|
void ZlibDecompressor::Cleanup() {
|
|||
|
if (initialized_) {
|
|||
|
inflateEnd(&stream_);
|
|||
|
initialized_ = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} // namespace ZlibCpp
|