/* */ #include "GZipDecoder.h" #include "StringFormat.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 DlAbortEx("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 DlAbortEx(StringFormat("libz::inflate() failed. cause:%s", _strm->msg).str()); } 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