rlm@1: // ZlibDecoder.cpp rlm@1: rlm@1: #include "StdAfx.h" rlm@1: rlm@1: #include "../Common/StreamUtils.h" rlm@1: rlm@1: #include "DeflateDecoder.h" rlm@1: #include "ZlibDecoder.h" rlm@1: rlm@1: namespace NCompress { rlm@1: namespace NZlib { rlm@1: rlm@1: #define DEFLATE_TRY_BEGIN try { rlm@1: #define DEFLATE_TRY_END } \ rlm@1: catch(...) { return S_FALSE; } rlm@1: rlm@1: #define ADLER_MOD 65521 rlm@1: #define ADLER_LOOP_MAX 5550 rlm@1: rlm@1: static UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size) rlm@1: { rlm@1: UInt32 a = adler & 0xFFFF; rlm@1: UInt32 b = (adler >> 16) & 0xFFFF; rlm@1: while (size > 0) rlm@1: { rlm@1: unsigned curSize = (size > ADLER_LOOP_MAX) ? ADLER_LOOP_MAX : (unsigned )size; rlm@1: unsigned i; rlm@1: for (i = 0; i < curSize; i++) rlm@1: { rlm@1: a += buf[i]; rlm@1: b += a; rlm@1: } rlm@1: buf += curSize; rlm@1: size -= curSize; rlm@1: a %= ADLER_MOD; rlm@1: b %= ADLER_MOD; rlm@1: } rlm@1: return (b << 16) + a; rlm@1: } rlm@1: rlm@1: STDMETHODIMP COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize) rlm@1: { rlm@1: HRESULT result = _stream->Write(data, size, &size); rlm@1: _adler = Adler32_Update(_adler, (const Byte *)data, size); rlm@1: if (processedSize != NULL) rlm@1: *processedSize = size; rlm@1: return result; rlm@1: } rlm@1: rlm@1: STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, rlm@1: const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) rlm@1: { rlm@1: DEFLATE_TRY_BEGIN rlm@1: if (!AdlerStream) rlm@1: { rlm@1: AdlerSpec = new COutStreamWithAdler; rlm@1: AdlerStream = AdlerSpec; rlm@1: } rlm@1: if (!DeflateDecoder) rlm@1: { rlm@1: DeflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; rlm@1: DeflateDecoderSpec->ZlibMode = true; rlm@1: DeflateDecoder = DeflateDecoderSpec; rlm@1: } rlm@1: rlm@1: Byte buf[2]; rlm@1: RINOK(ReadStream_FALSE(inStream, buf, 2)); rlm@1: int method = buf[0] & 0xF; rlm@1: if (method != 8) rlm@1: return S_FALSE; rlm@1: // int dicSize = buf[0] >> 4; rlm@1: if ((((UInt32)buf[0] << 8) + buf[1]) % 31 != 0) rlm@1: return S_FALSE; rlm@1: if ((buf[1] & 0x20) != 0) // dictPresent rlm@1: return S_FALSE; rlm@1: // int level = (buf[1] >> 6); rlm@1: rlm@1: AdlerSpec->SetStream(outStream); rlm@1: AdlerSpec->Init(); rlm@1: HRESULT res = DeflateDecoder->Code(inStream, AdlerStream, inSize, outSize, progress); rlm@1: AdlerSpec->ReleaseStream(); rlm@1: rlm@1: if (res == S_OK) rlm@1: { rlm@1: const Byte *p = DeflateDecoderSpec->ZlibFooter; rlm@1: UInt32 adler = ((UInt32)p[0] << 24) | ((UInt32)p[1] << 16) | ((UInt32)p[2] << 8) | p[3]; rlm@1: if (adler != AdlerSpec->GetAdler()) rlm@1: return S_FALSE; rlm@1: } rlm@1: return res; rlm@1: DEFLATE_TRY_END rlm@1: } rlm@1: rlm@1: }}