rlm@1
|
1 // ZlibDecoder.cpp
|
rlm@1
|
2
|
rlm@1
|
3 #include "StdAfx.h"
|
rlm@1
|
4
|
rlm@1
|
5 #include "../Common/StreamUtils.h"
|
rlm@1
|
6
|
rlm@1
|
7 #include "DeflateDecoder.h"
|
rlm@1
|
8 #include "ZlibDecoder.h"
|
rlm@1
|
9
|
rlm@1
|
10 namespace NCompress {
|
rlm@1
|
11 namespace NZlib {
|
rlm@1
|
12
|
rlm@1
|
13 #define DEFLATE_TRY_BEGIN try {
|
rlm@1
|
14 #define DEFLATE_TRY_END } \
|
rlm@1
|
15 catch(...) { return S_FALSE; }
|
rlm@1
|
16
|
rlm@1
|
17 #define ADLER_MOD 65521
|
rlm@1
|
18 #define ADLER_LOOP_MAX 5550
|
rlm@1
|
19
|
rlm@1
|
20 static UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size)
|
rlm@1
|
21 {
|
rlm@1
|
22 UInt32 a = adler & 0xFFFF;
|
rlm@1
|
23 UInt32 b = (adler >> 16) & 0xFFFF;
|
rlm@1
|
24 while (size > 0)
|
rlm@1
|
25 {
|
rlm@1
|
26 unsigned curSize = (size > ADLER_LOOP_MAX) ? ADLER_LOOP_MAX : (unsigned )size;
|
rlm@1
|
27 unsigned i;
|
rlm@1
|
28 for (i = 0; i < curSize; i++)
|
rlm@1
|
29 {
|
rlm@1
|
30 a += buf[i];
|
rlm@1
|
31 b += a;
|
rlm@1
|
32 }
|
rlm@1
|
33 buf += curSize;
|
rlm@1
|
34 size -= curSize;
|
rlm@1
|
35 a %= ADLER_MOD;
|
rlm@1
|
36 b %= ADLER_MOD;
|
rlm@1
|
37 }
|
rlm@1
|
38 return (b << 16) + a;
|
rlm@1
|
39 }
|
rlm@1
|
40
|
rlm@1
|
41 STDMETHODIMP COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
rlm@1
|
42 {
|
rlm@1
|
43 HRESULT result = _stream->Write(data, size, &size);
|
rlm@1
|
44 _adler = Adler32_Update(_adler, (const Byte *)data, size);
|
rlm@1
|
45 if (processedSize != NULL)
|
rlm@1
|
46 *processedSize = size;
|
rlm@1
|
47 return result;
|
rlm@1
|
48 }
|
rlm@1
|
49
|
rlm@1
|
50 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
rlm@1
|
51 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
rlm@1
|
52 {
|
rlm@1
|
53 DEFLATE_TRY_BEGIN
|
rlm@1
|
54 if (!AdlerStream)
|
rlm@1
|
55 {
|
rlm@1
|
56 AdlerSpec = new COutStreamWithAdler;
|
rlm@1
|
57 AdlerStream = AdlerSpec;
|
rlm@1
|
58 }
|
rlm@1
|
59 if (!DeflateDecoder)
|
rlm@1
|
60 {
|
rlm@1
|
61 DeflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
|
rlm@1
|
62 DeflateDecoderSpec->ZlibMode = true;
|
rlm@1
|
63 DeflateDecoder = DeflateDecoderSpec;
|
rlm@1
|
64 }
|
rlm@1
|
65
|
rlm@1
|
66 Byte buf[2];
|
rlm@1
|
67 RINOK(ReadStream_FALSE(inStream, buf, 2));
|
rlm@1
|
68 int method = buf[0] & 0xF;
|
rlm@1
|
69 if (method != 8)
|
rlm@1
|
70 return S_FALSE;
|
rlm@1
|
71 // int dicSize = buf[0] >> 4;
|
rlm@1
|
72 if ((((UInt32)buf[0] << 8) + buf[1]) % 31 != 0)
|
rlm@1
|
73 return S_FALSE;
|
rlm@1
|
74 if ((buf[1] & 0x20) != 0) // dictPresent
|
rlm@1
|
75 return S_FALSE;
|
rlm@1
|
76 // int level = (buf[1] >> 6);
|
rlm@1
|
77
|
rlm@1
|
78 AdlerSpec->SetStream(outStream);
|
rlm@1
|
79 AdlerSpec->Init();
|
rlm@1
|
80 HRESULT res = DeflateDecoder->Code(inStream, AdlerStream, inSize, outSize, progress);
|
rlm@1
|
81 AdlerSpec->ReleaseStream();
|
rlm@1
|
82
|
rlm@1
|
83 if (res == S_OK)
|
rlm@1
|
84 {
|
rlm@1
|
85 const Byte *p = DeflateDecoderSpec->ZlibFooter;
|
rlm@1
|
86 UInt32 adler = ((UInt32)p[0] << 24) | ((UInt32)p[1] << 16) | ((UInt32)p[2] << 8) | p[3];
|
rlm@1
|
87 if (adler != AdlerSpec->GetAdler())
|
rlm@1
|
88 return S_FALSE;
|
rlm@1
|
89 }
|
rlm@1
|
90 return res;
|
rlm@1
|
91 DEFLATE_TRY_END
|
rlm@1
|
92 }
|
rlm@1
|
93
|
rlm@1
|
94 }}
|