1 // ZlibDecoder.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/CpuArch.h"
6
7 #include "../Common/StreamUtils.h"
8
9 #include "ZlibDecoder.h"
10
11 namespace NCompress {
12 namespace NZlib {
13
14 #define DEFLATE_TRY_BEGIN try {
15 #define DEFLATE_TRY_END } catch(...) { return S_FALSE; }
16
17 #define ADLER_MOD 65521
18 #define ADLER_LOOP_MAX 5550
19
20 UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size);
Adler32_Update(UInt32 adler,const Byte * data,size_t size)21 UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size)
22 {
23 if (size == 0)
24 return adler;
25 UInt32 a = adler & 0xffff;
26 UInt32 b = adler >> 16;
27 do
28 {
29 size_t cur = size;
30 if (cur > ADLER_LOOP_MAX)
31 cur = ADLER_LOOP_MAX;
32 size -= cur;
33 const Byte *lim = data + cur;
34 if (cur >= 4)
35 {
36 lim -= 4 - 1;
37 do
38 {
39 a += data[0]; b += a;
40 a += data[1]; b += a;
41 a += data[2]; b += a;
42 a += data[3]; b += a;
43 data += 4;
44 }
45 while (data < lim);
46 lim += 4 - 1;
47 }
48 if (data != lim) { a += *data++; b += a;
49 if (data != lim) { a += *data++; b += a;
50 if (data != lim) { a += *data++; b += a; }}}
51 a %= ADLER_MOD;
52 b %= ADLER_MOD;
53 }
54 while (size);
55 return (b << 16) + a;
56 }
57
Z7_COM7F_IMF(COutStreamWithAdler::Write (const void * data,UInt32 size,UInt32 * processedSize))58 Z7_COM7F_IMF(COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize))
59 {
60 HRESULT result = S_OK;
61 if (_stream)
62 result = _stream->Write(data, size, &size);
63 _adler = Adler32_Update(_adler, (const Byte *)data, size);
64 _size += size;
65 if (processedSize)
66 *processedSize = size;
67 return result;
68 }
69
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))70 Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
71 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
72 {
73 DEFLATE_TRY_BEGIN
74 _inputProcessedSize_Additional = 0;
75 AdlerStream.Create_if_Empty();
76 DeflateDecoder.Create_if_Empty();
77 DeflateDecoder->Set_NeedFinishInput(true);
78
79 if (inSize && *inSize < 2)
80 return S_FALSE;
81 {
82 Byte buf[2];
83 RINOK(ReadStream_FALSE(inStream, buf, 2))
84 if (!IsZlib(buf))
85 return S_FALSE;
86 }
87 _inputProcessedSize_Additional = 2;
88 AdlerStream->SetStream(outStream);
89 AdlerStream->Init();
90 // NDeflate::NDecoder::Code() ignores inSize
91 /*
92 UInt64 inSize2 = 0;
93 if (inSize)
94 inSize2 = *inSize - 2;
95 */
96 const HRESULT res = DeflateDecoder.Interface()->Code(inStream, AdlerStream,
97 /* inSize ? &inSize2 : */ NULL, outSize, progress);
98 AdlerStream->ReleaseStream();
99
100 if (res == S_OK)
101 {
102 UInt32 footer32[1];
103 UInt32 processedSize;
104 RINOK(DeflateDecoder->ReadUnusedFromInBuf(footer32, 4, &processedSize))
105 if (processedSize != 4)
106 {
107 size_t processedSize2 = 4 - processedSize;
108 RINOK(ReadStream(inStream, (Byte *)(void *)footer32 + processedSize, &processedSize2))
109 _inputProcessedSize_Additional += (Int32)processedSize2;
110 processedSize += (UInt32)processedSize2;
111 }
112
113 if (processedSize == 4)
114 {
115 const UInt32 adler = GetBe32a(footer32);
116 if (adler != AdlerStream->GetAdler())
117 return S_FALSE; // adler error
118 }
119 else if (!IsAdlerOptional)
120 return S_FALSE; // unexpeced end of stream (can't read adler)
121 else
122 {
123 // IsAdlerOptional == true
124 if (processedSize != 0)
125 {
126 // we exclude adler bytes from processed size:
127 _inputProcessedSize_Additional -= (Int32)processedSize;
128 return S_FALSE;
129 }
130 }
131 }
132 return res;
133 DEFLATE_TRY_END
134 }
135
136 }}
137