/* */ #include "GZipDecoder.h" #include "fmt.h" #include "DlAbortEx.h" namespace aria2 { const std::string GZipDecoder::NAME("GZipDecoder"); GZipDecoder::GZipDecoder():strm_(0), finished_(false) {} GZipDecoder::~GZipDecoder() { release(); } void GZipDecoder::init() { finished_ = false; release(); strm_ = new z_stream(); strm_->zalloc = Z_NULL; strm_->zfree = Z_NULL; strm_->opaque = Z_NULL; strm_->avail_in = 0; strm_->next_in = Z_NULL; // initalize z_stream with gzip/zlib format auto detection enabled. if(Z_OK != inflateInit2(strm_, 47)) { throw DL_ABORT_EX("Initializing z_stream failed."); } } void GZipDecoder::release() { if(strm_) { inflateEnd(strm_); delete strm_; strm_ = 0; } } std::string GZipDecoder::decode(const unsigned char* in, size_t length) { std::string out; if(length == 0) { return out; } strm_->avail_in = length; strm_->next_in = const_cast(in); unsigned char outbuf[OUTBUF_LENGTH]; while(1) { strm_->avail_out = OUTBUF_LENGTH; strm_->next_out = outbuf; int ret = ::inflate(strm_, Z_NO_FLUSH); if(ret == Z_STREAM_END) { finished_ = true; } else if(ret != Z_OK) { throw DL_ABORT_EX(fmt("libz::inflate() failed. cause:%s", strm_->msg)); } size_t produced = OUTBUF_LENGTH-strm_->avail_out; out.append(&outbuf[0], &outbuf[produced]); if(strm_->avail_out > 0) { break; } } return out; } bool GZipDecoder::finished() { return finished_; } const std::string& GZipDecoder::getName() const { return NAME; } } // namespace aria2