This commit is contained in:
Igor Pavlov
2014-11-23 00:00:00 +00:00
committed by Kornel Lesiński
parent 83f8ddcc5b
commit f08f4dcc3c
1158 changed files with 76451 additions and 35082 deletions
+178 -43
View File
@@ -2,66 +2,65 @@
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "NsisDecode.h"
#include "../../Common/StreamUtils.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/MethodId.h"
#include "../../Compress/BcjCoder.h"
#include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h"
#define Get32(p) GetUi32(p)
namespace NArchive {
namespace NNsis {
static const CMethodId k_BCJ_X86 = 0x03030103;
HRESULT CDecoder::Init(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter)
HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{
useFilter = false;
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
if (_decoderInStream)
if (method != _method)
if (Method != _curMethod)
Release();
_method = method;
_curMethod = Method;
if (!_codecInStream)
{
switch (method)
switch (Method)
{
// case NMethodType::kCopy: return E_NOTIMPL;
case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;
case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;
case NMethodType::kLZMA:
_lzmaDecoder = new NCompress::NLzma::CDecoder();
_codecInStream = _lzmaDecoder;
break;
default: return E_NOTIMPL;
}
}
if (thereIsFilterFlag)
if (FilterFlag)
{
UInt32 processedSize;
BYTE flag;
RINOK(inStream->Read(&flag, 1, &processedSize));
if (processedSize != 1)
return E_FAIL;
Byte flag;
RINOK(ReadStream_FALSE(inStream, &flag, 1));
if (flag > 1)
return E_NOTIMPL;
useFilter = (flag != 0);
}
if (useFilter)
if (!useFilter)
_decoderInStream = _codecInStream;
else
{
if (!_filterInStream)
{
CMyComPtr<ICompressCoder> coder;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
k_BCJ_X86, coder, false));
if (!coder)
return E_NOTIMPL;
CFilterCoder *coderSpec = new CFilterCoder;
CMyComPtr<ICompressCoder> coder = coderSpec;
coderSpec->Filter = new CBCJ_x86_Decoder();
coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
if (!_filterInStream)
return E_NOTIMPL;
@@ -73,23 +72,13 @@ HRESULT CDecoder::Init(
RINOK(setInStream->SetInStream(_codecInStream));
_decoderInStream = _filterInStream;
}
else
_decoderInStream = _codecInStream;
if (method == NMethodType::kLZMA)
if (Method == NMethodType::kLZMA)
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
_codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
if (setDecoderProperties)
{
static const UInt32 kPropertiesSize = 5;
BYTE properties[kPropertiesSize];
UInt32 processedSize;
RINOK(inStream->Read(properties, kPropertiesSize, &processedSize));
if (processedSize != kPropertiesSize)
return E_FAIL;
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize));
}
const unsigned kPropsSize = LZMA_PROPS_SIZE;
Byte props[kPropsSize];
RINOK(ReadStream_FALSE(inStream, props, kPropsSize));
RINOK(_lzmaDecoder->SetDecoderProperties2((const Byte *)props, kPropsSize));
}
{
@@ -122,9 +111,155 @@ HRESULT CDecoder::Init(
return S_OK;
}
HRESULT CDecoder::Read(void *data, size_t *processedSize)
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress)
{
return ReadStream(_decoderInStream, data, processedSize);;
if (StreamPos > pos)
return E_FAIL;
UInt64 inSizeStart = 0;
if (_lzmaDecoder)
inSizeStart = _lzmaDecoder->GetInputProcessedSize();
UInt64 offset = 0;
while (StreamPos < pos)
{
size_t size = (size_t)MyMin(pos - StreamPos, (UInt64)Buffer.Size());
RINOK(Read(Buffer, &size));
if (size == 0)
return S_FALSE;
StreamPos += size;
offset += size;
UInt64 inSize = 0;
if (_lzmaDecoder)
inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart;
RINOK(progress->SetRatioInfo(&inSize, &offset));
}
return S_OK;
}
HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,
ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
UInt32 &packSizeRes, UInt32 &unpackSizeRes)
{
CLimitedSequentialInStream *limitedStreamSpec = NULL;
CMyComPtr<ISequentialInStream> limitedStream;
packSizeRes = 0;
unpackSizeRes = 0;
if (Solid)
{
Byte temp[4];
size_t processedSize = 4;
RINOK(Read(temp, &processedSize));
if (processedSize != 4)
return S_FALSE;
StreamPos += processedSize;
UInt32 size = Get32(temp);
if (unpackSizeDefined && size != unpackSize)
return S_FALSE;
unpackSize = size;
unpackSizeDefined = true;
}
else
{
Byte temp[4];
RINOK(ReadStream_FALSE(InputStream, temp, 4));
StreamPos += 4;
UInt32 size = Get32(temp);
if ((size & kMask_IsCompressed) == 0)
{
if (unpackSizeDefined && size != unpackSize)
return S_FALSE;
packSizeRes = size;
if (outBuf)
outBuf->Alloc(size);
UInt64 offset = 0;
while (size > 0)
{
UInt32 curSize = (UInt32)MyMin((size_t)size, Buffer.Size());
UInt32 processedSize;
RINOK(InputStream->Read(Buffer, curSize, &processedSize));
if (processedSize == 0)
return S_FALSE;
if (outBuf)
memcpy((Byte *)*outBuf + (size_t)offset, Buffer, processedSize);
offset += processedSize;
size -= processedSize;
StreamPos += processedSize;
unpackSizeRes += processedSize;
if (realOutStream)
RINOK(WriteStream(realOutStream, Buffer, processedSize));
RINOK(progress->SetRatioInfo(&offset, &offset));
}
return S_OK;
}
size &= ~kMask_IsCompressed;
packSizeRes = size;
limitedStreamSpec = new CLimitedSequentialInStream;
limitedStream = limitedStreamSpec;
limitedStreamSpec->SetStream(InputStream);
limitedStreamSpec->Init(size);
{
bool useFilter;
RINOK(Init(limitedStream, useFilter));
}
}
if (outBuf)
{
if (!unpackSizeDefined)
return S_FALSE;
outBuf->Alloc(unpackSize);
}
UInt64 inSizeStart = 0;
if (_lzmaDecoder)
inSizeStart = _lzmaDecoder->GetInputProcessedSize();
// we don't allow files larger than 4 GB;
if (!unpackSizeDefined)
unpackSize = 0xFFFFFFFF;
UInt32 offset = 0;
for (;;)
{
size_t rem = unpackSize - offset;
if (rem == 0)
break;
size_t size = Buffer.Size();
if (size > rem)
size = rem;
RINOK(Read(Buffer, &size));
if (size == 0)
{
if (unpackSizeDefined)
return S_FALSE;
break;
}
if (outBuf)
memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size);
StreamPos += size;
offset += (UInt32)size;
UInt64 inSize = 0; // it can be improved: we need inSize for Deflate and BZip2 too.
if (_lzmaDecoder)
inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart;
if (Solid)
packSizeRes = (UInt32)inSize;
unpackSizeRes += (UInt32)size;
UInt64 outSize = offset;
RINOK(progress->SetRatioInfo(&inSize, &outSize));
if (realOutStream)
RINOK(WriteStream(realOutStream, Buffer, size));
}
return S_OK;
}
}}