xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/ZlibDecoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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