This commit is contained in:
Igor Pavlov
2010-09-08 00:00:00 +00:00
committed by Kornel Lesiński
parent e279500d76
commit 044e4bb741
30 changed files with 399 additions and 148 deletions

View File

@@ -7,15 +7,14 @@
#include "../../Common/StreamUtils.h"
#include "../../Common/MethodId.h"
#include "../../Common/CreateCoder.h"
#include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h"
namespace NArchive {
namespace NNsis {
static const CMethodId k_Copy = 0x0;
static const CMethodId k_Deflate = 0x040901;
static const CMethodId k_BZip2 = 0x040902;
static const CMethodId k_LZMA = 0x030101;
static const CMethodId k_BCJ_X86 = 0x03030103;
HRESULT CDecoder::Init(
@@ -31,24 +30,14 @@ HRESULT CDecoder::Init(
_method = method;
if (!_codecInStream)
{
CMethodId methodID;
switch (method)
{
case NMethodType::kCopy: methodID = k_Copy; break;
case NMethodType::kDeflate: methodID = k_Deflate; break;
case NMethodType::kBZip2: methodID = k_BZip2; break;
case NMethodType::kLZMA: methodID = k_LZMA; break;
// 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;
default: return E_NOTIMPL;
}
CMyComPtr<ICompressCoder> coder;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodID, coder, false));
if (!coder)
return E_NOTIMPL;
coder.QueryInterface(IID_ISequentialInStream, &_codecInStream);
if (!_codecInStream)
return E_NOTIMPL;
}
if (thereIsFilterFlag)

View File

@@ -87,7 +87,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosit
COM_TRY_BEGIN
Close();
{
if(_archive.Open(
if (_archive.Open(
EXTERNAL_CODECS_VARS
stream, maxCheckStartPosition) != S_OK)
return S_FALSE;
@@ -264,12 +264,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
GetNumberOfItems(&numItems);
if(numItems == 0)
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for(i = 0; i < numItems; i++)
for (i = 0; i < numItems; i++)
{
UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef NSIS_SCRIPT
@@ -313,6 +313,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
byteBuf.SetCapacity(kBufferLength);
Byte *buffer = byteBuf;
CByteBuffer tempBuf;
bool dataError = false;
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
{
@@ -330,7 +332,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (index >= (UInt32)_archive.Items.Size())
{
currentItemSize = _archive.Script.Length();
if(!testMode && !realOutStream)
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (!testMode)
@@ -346,7 +348,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
GetCompressedSize(index, currentItemSize);
if(!testMode && !realOutStream)
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
@@ -357,10 +359,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool sizeIsKnown = false;
UInt32 fullSize = 0;
bool writeToTemp = false;
bool readFromTemp = false;
if (_archive.IsSolid)
{
UInt64 pos = _archive.GetPosOfSolidItem(index);
while(streamPos < pos)
while (streamPos < pos)
{
size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
@@ -389,7 +394,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
fullSize = Get32(buffer2);
sizeIsKnown = true;
needDecompress = true;
if (!testMode && i + 1 < numItems)
{
UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]);
if (nextPos < streamPos + fullSize)
{
tempBuf.Free();
tempBuf.SetCapacity(fullSize);
writeToTemp = true;
}
}
}
else
readFromTemp = true;
}
else
{
@@ -413,7 +431,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (needDecompress)
{
UInt64 offset = 0;
while(!sizeIsKnown || fullSize > 0)
while (!sizeIsKnown || fullSize > 0)
{
UInt32 curSize = kBufferLength;
if (sizeIsKnown && curSize > fullSize)
@@ -433,6 +451,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
dataError = true;
break;
}
if (writeToTemp)
memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);
fullSize -= (UInt32)processedSize;
streamPos += processedSize;
@@ -450,7 +471,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else
{
while(fullSize > 0)
if (readFromTemp)
{
if (!testMode)
RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));
}
else
while (fullSize > 0)
{
UInt32 curSize = MyMin(fullSize, kBufferLength);
UInt32 processedSize;

View File

@@ -1151,16 +1151,25 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
bool sameName = IsUnicode ?
(Items[i].NameU == Items[i + 1].NameU) :
(Items[i].NameA == Items[i + 1].NameA);
if (Items[i].Pos == Items[i + 1].Pos && (IsSolid || sameName))
if (Items[i].Pos == Items[i + 1].Pos && sameName)
Items.Delete(i + 1);
else
i++;
}
for (i = 0; i + 1 < Items.Size(); i++)
for (i = 0; i < Items.Size(); i++)
{
CItem &item = Items[i];
item.EstimatedSizeIsDefined = true;
item.EstimatedSize = Items[i + 1].Pos - item.Pos - 4;
UInt32 curPos = item.Pos + 4;
for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
{
UInt32 nextPos = Items[nextIndex].Pos;
if (curPos <= nextPos)
{
item.EstimatedSizeIsDefined = true;
item.EstimatedSize = nextPos - curPos;
break;
}
}
}
if (!IsSolid)
{
@@ -1275,6 +1284,11 @@ static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
return false;
}
static bool IsBZip2(const Byte *p)
{
return (p[0] == 0x31 && p[1] < 14);
}
HRESULT CInArchive::Open2(
DECL_EXTERNAL_CODECS_LOC_VARS2
)
@@ -1312,7 +1326,14 @@ HRESULT CInArchive::Open2(
else if (sig[3] == 0x80)
{
IsSolid = false;
Method = NMethodType::kDeflate;
if (IsBZip2(sig + 4))
Method = NMethodType::kBZip2;
else
Method = NMethodType::kDeflate;
}
else if (IsBZip2(sig))
{
Method = NMethodType::kBZip2;
}
else
{