Files
nsis-plugin-ns7zip/versions/26.00/CPP/7zip/Compress/ZlibDecoder.cpp
T
Simone d074cc7c07 chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0
Architectures: x86-ansi, x86-unicode, amd64-unicode
License: LGPL-2.1-or-later
2026-04-29 14:07:51 +02:00

137 lines
3.3 KiB
C++

// ZlibDecoder.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "../Common/StreamUtils.h"
#include "ZlibDecoder.h"
namespace NCompress {
namespace NZlib {
#define DEFLATE_TRY_BEGIN try {
#define DEFLATE_TRY_END } catch(...) { return S_FALSE; }
#define ADLER_MOD 65521
#define ADLER_LOOP_MAX 5550
UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size);
UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size)
{
if (size == 0)
return adler;
UInt32 a = adler & 0xffff;
UInt32 b = adler >> 16;
do
{
size_t cur = size;
if (cur > ADLER_LOOP_MAX)
cur = ADLER_LOOP_MAX;
size -= cur;
const Byte *lim = data + cur;
if (cur >= 4)
{
lim -= 4 - 1;
do
{
a += data[0]; b += a;
a += data[1]; b += a;
a += data[2]; b += a;
a += data[3]; b += a;
data += 4;
}
while (data < lim);
lim += 4 - 1;
}
if (data != lim) { a += *data++; b += a;
if (data != lim) { a += *data++; b += a;
if (data != lim) { a += *data++; b += a; }}}
a %= ADLER_MOD;
b %= ADLER_MOD;
}
while (size);
return (b << 16) + a;
}
Z7_COM7F_IMF(COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize))
{
HRESULT result = S_OK;
if (_stream)
result = _stream->Write(data, size, &size);
_adler = Adler32_Update(_adler, (const Byte *)data, size);
_size += size;
if (processedSize)
*processedSize = size;
return result;
}
Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
{
DEFLATE_TRY_BEGIN
_inputProcessedSize_Additional = 0;
AdlerStream.Create_if_Empty();
DeflateDecoder.Create_if_Empty();
DeflateDecoder->Set_NeedFinishInput(true);
if (inSize && *inSize < 2)
return S_FALSE;
{
Byte buf[2];
RINOK(ReadStream_FALSE(inStream, buf, 2))
if (!IsZlib(buf))
return S_FALSE;
}
_inputProcessedSize_Additional = 2;
AdlerStream->SetStream(outStream);
AdlerStream->Init();
// NDeflate::NDecoder::Code() ignores inSize
/*
UInt64 inSize2 = 0;
if (inSize)
inSize2 = *inSize - 2;
*/
const HRESULT res = DeflateDecoder.Interface()->Code(inStream, AdlerStream,
/* inSize ? &inSize2 : */ NULL, outSize, progress);
AdlerStream->ReleaseStream();
if (res == S_OK)
{
UInt32 footer32[1];
UInt32 processedSize;
RINOK(DeflateDecoder->ReadUnusedFromInBuf(footer32, 4, &processedSize))
if (processedSize != 4)
{
size_t processedSize2 = 4 - processedSize;
RINOK(ReadStream(inStream, (Byte *)(void *)footer32 + processedSize, &processedSize2))
_inputProcessedSize_Additional += (Int32)processedSize2;
processedSize += (UInt32)processedSize2;
}
if (processedSize == 4)
{
const UInt32 adler = GetBe32a(footer32);
if (adler != AdlerStream->GetAdler())
return S_FALSE; // adler error
}
else if (!IsAdlerOptional)
return S_FALSE; // unexpeced end of stream (can't read adler)
else
{
// IsAdlerOptional == true
if (processedSize != 0)
{
// we exclude adler bytes from processed size:
_inputProcessedSize_Additional -= (Int32)processedSize;
return S_FALSE;
}
}
}
return res;
DEFLATE_TRY_END
}
}}