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