d074cc7c07
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
137 lines
3.3 KiB
C++
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
|
|
}
|
|
|
|
}}
|