aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/7z
diff options
context:
space:
mode:
authorTetsuo Osaka <tetsugit@gmail.com>2016-10-18 15:12:28 +0200
committerTetsuo Osaka <tetsugit@gmail.com>2017-04-18 10:07:58 +0200
commitf955a79a9fffb09826cf7547f70d08c3798a2f50 (patch)
tree7ba3acdf7ba22cb749ffd9e6a868630e5a8382f2 /CPP/7zip/Archive/7z
parent462f68aa279e25fda265a87c6d3c4da3318314f8 (diff)
downloadlzma-f955a79a9fffb09826cf7547f70d08c3798a2f50.tar.gz
Rebase LZMA SDK on 16.04 stable
This was downloaded from http://www.7-zip.org/a/lzma1604.7z The bin folder was excluded like in previous updates All files were deleted and replaced with those from the SDK. The embedded projects Tukaani, xz-embedded and android build files where not touched. The changelog since the 9.38 beta is: 16.04 2016-10-04 ------------------------- - The bug was fixed in DllSecur.c. 16.03 2016-09-28 ------------------------- - SFX modules now use some protection against DLL preloading attack. - Some bugs in 7z code were fixed. 16.02 2016-05-21 ------------------------- - The BUG in 16.00 - 16.01 was fixed: Split Handler (SplitHandler.cpp) returned incorrect total size value (kpidSize) for split archives. 16.01 2016-05-19 ------------------------- - Some internal changes to reduce the number of compiler warnings. 16.00 2016-05-10 ------------------------- - Some bugs were fixed. 15.12 2015-11-19 ------------------------- - The BUG in C version of 7z decoder was fixed: 7zDec.c : SzDecodeLzma2() 7z decoder could mistakenly report about decoding error for some 7z archives that use LZMA2 compression method. The probability to get that mistaken decoding error report was about one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). - The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: 7zArcIn.c : SzReadHeader2() 7z decoder worked incorrectly for 7z archives that contain empty solid blocks, that can be placed to 7z archive, if some file is unavailable for reading during archive creation. 15.09 beta 2015-10-16 ------------------------- - The BUG in LZMA / LZMA2 encoding code was fixed. The BUG in LzFind.c::MatchFinder_ReadBlock() function. If input data size is larger than (4 GiB - dictionary_size), the following code worked incorrectly: - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions for compressing from memory to memory. That BUG is not related to LZMA encoder version that works via streams. - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if default value of chunk size (CLzma2EncProps::blockSize) is changed to value larger than (4 GiB - dictionary_size). Change-Id: I6b3974015c605fba3c0d4d897fab5a166174f441
Diffstat (limited to 'CPP/7zip/Archive/7z')
-rw-r--r--CPP/7zip/Archive/7z/7zCompressionMode.h43
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp532
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.h51
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp584
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.h67
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp472
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.cpp133
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.h39
-rw-r--r--CPP/7zip/Archive/7z/7zFolderOutStream.cpp149
-rw-r--r--CPP/7zip/Archive/7z/7zFolderOutStream.h58
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.cpp94
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h34
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp218
-rw-r--r--CPP/7zip/Archive/7z/7zHeader.h47
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp312
-rw-r--r--CPP/7zip/Archive/7z/7zIn.h59
-rw-r--r--CPP/7zip/Archive/7z/7zItem.h63
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp99
-rw-r--r--CPP/7zip/Archive/7z/7zOut.h4
-rw-r--r--CPP/7zip/Archive/7z/7zProperties.cpp62
-rw-r--r--CPP/7zip/Archive/7z/7zRegister.cpp14
-rw-r--r--CPP/7zip/Archive/7z/7zSpecStream.h10
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp1698
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.h31
24 files changed, 3242 insertions, 1631 deletions
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 3301b93..80e4154 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -9,37 +9,62 @@
namespace NArchive {
namespace N7z {
-struct CMethodFull: public CProps
+struct CMethodFull: public CMethodProps
{
CMethodId Id;
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ UInt32 NumStreams;
- bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+ bool IsSimpleCoder() const { return NumStreams == 1; }
};
-struct CBind
+struct CBond2
{
- UInt32 InCoder;
- UInt32 InStream;
UInt32 OutCoder;
UInt32 OutStream;
+ UInt32 InCoder;
};
struct CCompressionMethodMode
{
+ /*
+ if (Bonds.Empty()), then default bonds must be created
+ if (Filter_was_Inserted)
+ {
+ Methods[0] is filter method
+ Bonds don't contain bonds for filter (these bonds must be created)
+ }
+ */
+
CObjectVector<CMethodFull> Methods;
- CRecordVector<CBind> Binds;
+ CRecordVector<CBond2> Bonds;
+
+ bool IsThereBond_to_Coder(unsigned coderIndex) const
+ {
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].InCoder == coderIndex)
+ return true;
+ return false;
+ }
+
+ bool DefaultMethod_was_Inserted;
+ bool Filter_was_Inserted;
+
#ifndef _7ZIP_ST
UInt32 NumThreads;
+ bool MultiThreadMixer;
#endif
+
bool PasswordIsDefined;
UString Password;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
- CCompressionMethodMode(): PasswordIsDefined(false)
+ CCompressionMethodMode():
+ DefaultMethod_was_Inserted(false),
+ Filter_was_Inserted(false),
+ PasswordIsDefined(false)
#ifndef _7ZIP_ST
, NumThreads(1)
+ , MultiThreadMixer(true)
#endif
{}
};
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index d58fb02..1f709cb 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#include "../../Common/LimitedStreams.h"
-#include "../../Common/LockedStream.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
@@ -12,50 +11,70 @@
namespace NArchive {
namespace N7z {
-static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
- CBindInfoEx &bindInfo)
+class CDecProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- bindInfo.Clear();
- bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
+ CMyComPtr<ICompressProgressInfo> _progress;
+public:
+ CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
+{
+ return _progress->SetRatioInfo(NULL, outSize);
+}
+
+static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
+{
+ bi.Clear();
+
+ bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
unsigned i;
- for (i = 0; i < folder.BindPairs.Size(); i++)
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
- bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
- bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
+ NCoderMixer2::CBond &bond = bi.Bonds[i];
+ const N7z::CBond &folderBond = folder.Bonds[i];
+ bond.PackIndex = folderBond.PackIndex;
+ bond.UnpackIndex = folderBond.UnpackIndex;
}
- bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
- bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
-
- UInt32 outStreamIndex = 0;
+ bi.Coders.ClearAndSetSize(folder.Coders.Size());
+ bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
for (i = 0; i < folder.Coders.Size(); i++)
{
- NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
const CCoderInfo &coderInfo = folder.Coders[i];
- coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
- coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
- bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
- for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
- if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
- bindInfo.OutStreams.Add(outStreamIndex);
+ bi.Coders[i].NumStreams = coderInfo.NumStreams;
+ bi.CoderMethodIDs[i] = coderInfo.MethodID;
}
- bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
+
+ /*
+ if (!bi.SetUnpackCoder())
+ throw 1112;
+ */
+ bi.UnpackCoder = folder.UnpackCoder;
+ bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
for (i = 0; i < folder.PackStreams.Size(); i++)
- bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
+ bi.PackStreams[i] = folder.PackStreams[i];
}
-static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
- const NCoderMixer::CCoderStreamsInfo &a2)
+static inline bool AreCodersEqual(
+ const NCoderMixer2::CCoderStreamsInfo &a1,
+ const NCoderMixer2::CCoderStreamsInfo &a2)
{
- return (a1.NumInStreams == a2.NumInStreams) &&
- (a1.NumOutStreams == a2.NumOutStreams);
+ return (a1.NumStreams == a2.NumStreams);
}
-static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
+static inline bool AreBondsEqual(
+ const NCoderMixer2::CBond &a1,
+ const NCoderMixer2::CBond &a2)
{
- return (a1.InIndex == a2.InIndex) &&
- (a1.OutIndex == a2.OutIndex);
+ return
+ (a1.PackIndex == a2.PackIndex) &&
+ (a1.UnpackIndex == a2.UnpackIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
@@ -66,186 +85,290 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false;
- if (a1.BindPairs.Size() != a2.BindPairs.Size())
+
+ if (a1.Bonds.Size() != a2.Bonds.Size())
return false;
- for (i = 0; i < a1.BindPairs.Size(); i++)
- if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+ for (i = 0; i < a1.Bonds.Size(); i++)
+ if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
return false;
+
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false;
- if (a1.InStreams.Size() != a2.InStreams.Size())
+
+ if (a1.PackStreams.Size() != a2.PackStreams.Size())
return false;
- if (a1.OutStreams.Size() != a2.OutStreams.Size())
+ for (i = 0; i < a1.PackStreams.Size(); i++)
+ if (a1.PackStreams[i] != a2.PackStreams[i])
+ return false;
+
+ /*
+ if (a1.UnpackCoder != a2.UnpackCoder)
return false;
+ */
return true;
}
-CDecoder::CDecoder(bool multiThread)
+CDecoder::CDecoder(bool useMixerMT):
+ _bindInfoPrev_Defined(false),
+ _useMixerMT(useMixerMT)
+{}
+
+
+struct CLockedInStream:
+ public IUnknown,
+ public CMyUnknownImp
{
- #ifndef _ST_MODE
- multiThread = true;
+ CMyComPtr<IInStream> Stream;
+ UInt64 Pos;
+
+ MY_UNKNOWN_IMP
+
+ #ifdef USE_MIXER_MT
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
- _multiThread = multiThread;
- _bindInfoExPrevIsDefined = false;
+};
+
+
+#ifdef USE_MIXER_MT
+
+class CLockedSequentialInStreamMT:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
+
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
+}
+
+#endif
+
+
+#ifdef USE_MIXER_ST
+
+class CLockedSequentialInStreamST:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
}
+#endif
+
+
+
HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const CFolders &folders, int folderIndex,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **
+
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
+ #endif
+
_7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
)
{
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
- CFolder folderInfo;
- folders.ParseFolderInfo(folderIndex, folderInfo);
+ CFolderEx folderInfo;
+ folders.ParseFolderEx(folderIndex, folderInfo);
- if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
+ if (!folderInfo.IsDecodingSupported())
+ return E_NOTIMPL;
+
+ CBindInfoEx bindInfo;
+ Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
+ if (!bindInfo.CalcMapsAndCheck())
return E_NOTIMPL;
+ UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
+ bool fullUnpack = true;
+ if (unpackSize)
+ {
+ if (*unpackSize > folderUnpackSize)
+ return E_FAIL;
+ fullUnpack = (*unpackSize == folderUnpackSize);
+ }
+
/*
We don't need to init isEncrypted and passwordIsDefined
We must upgrade them only
+
#ifndef _NO_CRYPTO
isEncrypted = false;
passwordIsDefined = false;
#endif
*/
-
- CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
- CLockedInStream lockedInStream;
- lockedInStream.Init(inStream);
-
- for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
{
- CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
- CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
- lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> inStream = streamSpec;
- streamSpec->SetStream(lockedStreamImp);
- streamSpec->Init(packPositions[j + 1] - packPositions[j]);
- inStreams.Add(inStream);
- }
-
- unsigned numCoders = folderInfo.Coders.Size();
-
- CBindInfoEx bindInfo;
- ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
- bool createNewCoders;
- if (!_bindInfoExPrevIsDefined)
- createNewCoders = true;
- else
- createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
- if (createNewCoders)
- {
- unsigned i;
- _decoders.Clear();
- // _decoders2.Clear();
-
- _mixerCoder.Release();
+ _mixerRef.Release();
- if (_multiThread)
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT)
+ #endif
{
- _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderMTSpec;
- _mixerCoderCommon = _mixerCoderMTSpec;
+ _mixerMT = new NCoderMixer2::CMixerMT(false);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
}
+ #ifdef USE_MIXER_ST
else
+ #endif
+ #endif
{
- #ifdef _ST_MODE
- _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
- _mixerCoder = _mixerCoderSTSpec;
- _mixerCoderCommon = _mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(false);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
#endif
}
- RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
- for (i = 0; i < numCoders; i++)
+ RINOK(_mixer->SetBindInfo(bindInfo));
+
+ FOR_VECTOR(i, folderInfo.Coders)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ #ifndef _SFX
+ // we don't support RAR codecs here
+ if ((coderInfo.MethodID >> 8) == 0x403)
+ return E_NOTIMPL;
+ #endif
- CMyComPtr<ICompressCoder> decoder;
- CMyComPtr<ICompressCoder2> decoder2;
+ CCreatedCoder cod;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- coderInfo.MethodID, decoder, decoder2, false));
- CMyComPtr<IUnknown> decoderUnknown;
+ coderInfo.MethodID, false, cod));
+
if (coderInfo.IsSimpleCoder())
{
- if (decoder == 0)
+ if (!cod.Coder)
return E_NOTIMPL;
-
- decoderUnknown = (IUnknown *)decoder;
-
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder(decoder);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder(decoder, false);
- #endif
+ // CMethodId m = coderInfo.MethodID;
+ // isFilter = (IsFilterMethod(m) || m == k_AES);
}
else
{
- if (decoder2 == 0)
+ if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
return E_NOTIMPL;
- decoderUnknown = (IUnknown *)decoder2;
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder2(decoder2);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder2(decoder2, false);
- #endif
}
- _decoders.Add(decoderUnknown);
+ _mixer->AddCoder(cod);
+
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
}
- _bindInfoExPrev = bindInfo;
- _bindInfoExPrevIsDefined = true;
+
+ _bindInfoPrev = bindInfo;
+ _bindInfoPrev_Defined = true;
}
- unsigned i;
- _mixerCoderCommon->ReInit();
+
+ _mixer->ReInit();
UInt32 packStreamIndex = 0;
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
- UInt32 unpackStreamIndex = unpackStreamIndexStart;
- UInt32 coderIndex = 0;
- // UInt32 coder2Index = 0;
-
- for (i = 0; i < numCoders; i++)
+
+ unsigned i;
+
+ for (i = 0; i < folderInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
- CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
-
+ IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
+
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
- decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
if (setDecoderProperties)
{
const CByteBuffer &props = coderInfo.Props;
size_t size = props.Size();
if (size > 0xFFFFFFFF)
return E_NOTIMPL;
- // if (size > 0)
- {
- RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
- }
+ HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
+ if (res == E_INVALIDARG)
+ res = E_NOTIMPL;
+ RINOK(res);
}
}
@@ -253,7 +376,7 @@ HRESULT CDecoder::Decode(
if (mtMode)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
- decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
@@ -264,7 +387,7 @@ HRESULT CDecoder::Decode(
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
- decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+ decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
if (cryptoSetPassword)
{
isEncrypted = true;
@@ -273,71 +396,148 @@ HRESULT CDecoder::Decode(
CMyComBSTR passwordBSTR;
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
passwordIsDefined = true;
+ password.Empty();
size_t len = 0;
if (passwordBSTR)
- len = MyStringLen((BSTR)passwordBSTR);
+ {
+ password = passwordBSTR;
+ len = password.Len();
+ }
CByteBuffer buffer(len * 2);
- for (size_t i = 0; i < len; i++)
+ for (size_t k = 0; k < len; k++)
{
- wchar_t c = passwordBSTR[i];
- ((Byte *)buffer)[i * 2] = (Byte)c;
- ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ wchar_t c = passwordBSTR[k];
+ ((Byte *)buffer)[k * 2] = (Byte)c;
+ ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
}
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
}
}
#endif
- coderIndex++;
+ {
+ CMyComPtr<ICompressSetFinishMode> setFinishMode;
+ decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
+ if (setFinishMode)
+ {
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
+ }
+ }
- UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
- UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
- CObjArray<UInt64> packSizes(numInStreams);
- CObjArray<const UInt64 *> packSizesPointers(numInStreams);
- CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
- UInt32 j;
-
- for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
- unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
+ UInt32 numStreams = (UInt32)coderInfo.NumStreams;
- for (j = 0; j < numInStreams; j++, packStreamIndex++)
+ CObjArray<UInt64> packSizes(numStreams);
+ CObjArray<const UInt64 *> packSizesPointers(numStreams);
+
+ for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
{
- int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
- if (bindPairIndex >= 0)
- packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
+ int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
+
+ if (bond >= 0)
+ packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
else
{
- int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+ int index = folderInfo.Find_in_PackStreams(packStreamIndex);
if (index < 0)
- return S_FALSE; // check it
- packSizes[j] = packPositions[index + 1] - packPositions[index];
+ return E_NOTIMPL;
+ packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
packSizesPointers[j] = &packSizes[j];
}
}
+
+ const UInt64 *unpackSizesPointer =
+ (unpackSize && i == bindInfo.UnpackCoder) ?
+ unpackSize :
+ &folders.CoderUnpackSizes[unpackStreamIndexStart + i];
- _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
}
- UInt32 mainCoder, temp;
- bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
- if (_multiThread)
- _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
- /*
- else
- _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
- */
+ if (outStream)
+ {
+ _mixer->SelectMainCoder(!fullUnpack);
+ }
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+
+ CLockedInStream *lockedInStreamSpec = new CLockedInStream;
+ CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
+
+ bool needMtLock = false;
+
+ if (folderInfo.PackStreams.Size() > 1)
+ {
+ // lockedInStream.Pos = (UInt64)(Int64)-1;
+ // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
+ RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
+ lockedInStreamSpec->Stream = inStream;
+
+ #ifdef USE_MIXER_ST
+ if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
+ #endif
+ needMtLock = true;
+ }
+
+ for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ {
+ CMyComPtr<ISequentialInStream> packStream;
+ UInt64 packPos = startPos + packPositions[j];
+
+ if (folderInfo.PackStreams.Size() == 1)
+ {
+ RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
+ packStream = inStream;
+ }
+ else
+ {
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT || needMtLock)
+ #endif
+ {
+ CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ #endif
+ }
+ }
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ inStreams.AddNew() = streamSpec;
+ streamSpec->SetStream(packStream);
+ streamSpec->Init(packPositions[j + 1] - packPositions[j]);
+ }
- if (numCoders == 0)
- return 0;
unsigned num = inStreams.Size();
CObjArray<ISequentialInStream *> inStreamPointers(num);
for (i = 0; i < num; i++)
inStreamPointers[i] = inStreams[i];
- ISequentialOutStream *outStreamPointer = outStream;
- return _mixerCoder->Code(
- inStreamPointers, NULL, num,
- &outStreamPointer, NULL, 1,
- compressProgress);
+
+ if (outStream)
+ {
+ CMyComPtr<ICompressProgressInfo> progress2;
+ if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
+ progress2 = new CDecProgress(compressProgress);
+
+ ISequentialOutStream *outStreamPointer = outStream;
+ return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
+ }
+
+ #ifdef USE_MIXER_ST
+ return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
+ #else
+ return E_FAIL;
+ #endif
}
}}
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
index f27170d..051f843 100644
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -3,25 +3,17 @@
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
-#include "../../IStream.h"
-#include "../../IPassword.h"
-
#include "../Common/CoderMixer2.h"
-#include "../Common/CoderMixer2MT.h"
-#ifdef _ST_MODE
-#include "../Common/CoderMixer2ST.h"
-#endif
-
-#include "../../Common/CreateCoder.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
-struct CBindInfoEx: public NCoderMixer::CBindInfo
+struct CBindInfoEx: public NCoderMixer2::CBindInfo
{
CRecordVector<CMethodId> CoderMethodIDs;
+
void Clear()
{
CBindInfo::Clear();
@@ -31,29 +23,40 @@ struct CBindInfoEx: public NCoderMixer::CBindInfo
class CDecoder
{
- bool _bindInfoExPrevIsDefined;
- CBindInfoEx _bindInfoExPrev;
+ bool _bindInfoPrev_Defined;
+ CBindInfoEx _bindInfoPrev;
+
+ bool _useMixerMT;
- bool _multiThread;
- #ifdef _ST_MODE
- NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
#endif
- NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
- NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
- CMyComPtr<ICompressCoder2> _mixerCoder;
- CObjectVector<CMyComPtr<IUnknown> > _decoders;
- // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
+
public:
- CDecoder(bool multiThread);
+
+ CDecoder(bool useMixerMT);
+
HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const CFolders &folders, int folderIndex,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize // if (!unpackSize), then full folder is required
+ // if (unpackSize), then only *unpackSize bytes from folder are required
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 365489c..7636c60 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -12,43 +12,80 @@
#include "7zEncode.h"
#include "7zSpecStream.h"
-static const UInt64 k_Delta = 0x03;
-static const UInt64 k_BCJ = 0x03030103;
-static const UInt64 k_BCJ2 = 0x0303011B;
-
namespace NArchive {
namespace N7z {
-static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
- const CRecordVector<CMethodId> decompressionMethods,
- CFolder &folder)
+void CEncoder::InitBindConv()
+{
+ unsigned numIn = _bindInfo.Coders.Size();
+
+ _SrcIn_to_DestOut.ClearAndSetSize(numIn);
+ _DestOut_to_SrcIn.ClearAndSetSize(numIn);
+
+ unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
+ _SrcOut_to_DestIn.ClearAndSetSize(numOut);
+ // _DestIn_to_SrcOut.ClearAndSetSize(numOut);
+
+ UInt32 destIn = 0;
+ UInt32 destOut = 0;
+
+ for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
+ {
+ i--;
+
+ const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
+
+ numIn--;
+ numOut -= coder.NumStreams;
+
+ _SrcIn_to_DestOut[numIn] = destOut;
+ _DestOut_to_SrcIn[destOut] = numIn;
+
+ destOut++;
+
+ for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
+ {
+ UInt32 index = numOut + j;
+ _SrcOut_to_DestIn[index] = destIn;
+ // _DestIn_to_SrcOut[destIn] = index;
+ }
+ }
+}
+
+void CEncoder::SetFolder(CFolder &folder)
{
- // bindInfo.CoderMethodIDs.Clear();
- // folder.OutStreams.Clear();
- folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
+ folder.Bonds.SetSize(_bindInfo.Bonds.Size());
+
unsigned i;
- for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+
+ for (i = 0; i < _bindInfo.Bonds.Size(); i++)
{
- CBindPair &bp = folder.BindPairs[i];
- const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
- bp.InIndex = mixerBp.InIndex;
- bp.OutIndex = mixerBp.OutIndex;
+ CBond &fb = folder.Bonds[i];
+ const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
+ fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex];
+ fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex];
}
- folder.Coders.SetSize(bindInfo.Coders.Size());
- for (i = 0; i < bindInfo.Coders.Size(); i++)
+
+ folder.Coders.SetSize(_bindInfo.Coders.Size());
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
CCoderInfo &coderInfo = folder.Coders[i];
- const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
- coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
- coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
- coderInfo.MethodID = decompressionMethods[i];
- // coderInfo.Props can be nonFree;
+ const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
+
+ coderInfo.NumStreams = coderStreamsInfo.NumStreams;
+ coderInfo.MethodID = _decompressionMethods[i];
+ // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
}
- folder.PackStreams.SetSize(bindInfo.InStreams.Size());
- for (i = 0; i < bindInfo.InStreams.Size(); i++)
- folder.PackStreams[i] = bindInfo.InStreams[i];
+
+ folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
+
+ for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
+ folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
}
+
+
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
{
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
@@ -58,30 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce,
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
}
+
+
+void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
+{
+ _progress = progress;
+ OutSize = 0;
+}
+
+STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ UInt64 outSize2;
+ {
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+ #endif
+ outSize2 = OutSize;
+ }
+
+ if (_progress)
+ return _progress->SetRatioInfo(inSize, &outSize2);
+
+ return S_OK;
+}
+
+
+
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
{
- _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderSpec;
- RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
- FOR_VECTOR (i, _options.Methods)
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_options.MultiThreadMixer)
+ #endif
{
- const CMethodFull &methodFull = _options.Methods[i];
- CCoderInfo &encodingInfo = _codersInfo.AddNew();
- encodingInfo.MethodID = methodFull.Id;
- CMyComPtr<ICompressCoder> encoder;
- CMyComPtr<ICompressCoder2> encoder2;
-
+ _mixerMT = new NCoderMixer2::CMixerMT(true);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(true);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
+ #endif
+ }
+ RINOK(_mixer->SetBindInfo(_bindInfo));
+
+ FOR_VECTOR (m, _options.Methods)
+ {
+ const CMethodFull &methodFull = _options.Methods[m];
+
+ CCreatedCoder cod;
+
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- methodFull.Id, encoder, encoder2, true));
+ methodFull.Id, true, cod));
- if (!encoder && !encoder2)
+ if (cod.NumStreams != methodFull.NumStreams)
+ return E_FAIL;
+ if (!cod.Coder && !cod.Coder2)
return E_FAIL;
- CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
+ CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef _7ZIP_ST
{
@@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder(
}
*/
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
- const UInt32 sizeInBytes = _options.Password.Len() * 2;
+ const unsigned sizeInBytes = _options.Password.Len() * 2;
CByteBuffer buffer(sizeInBytes);
for (unsigned i = 0; i < _options.Password.Len(); i++)
{
@@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder(
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
- RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
}
- if (encoder)
- _mixerCoderSpec->AddCoder(encoder);
- else
- _mixerCoderSpec->AddCoder2(encoder2);
+ _mixer->AddCoder(cod);
+ }
+ return S_OK;
+}
+
+
+
+class CSequentialOutTempBufferImp2:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CInOutTempBuffer *_buf;
+public:
+ CMtEncMultiProgress *_mtProgresSpec;
+
+ CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}
+ void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
+{
+ if (!_buf->Write(data, size))
+ {
+ if (processed)
+ *processed = 0;
+ return E_FAIL;
}
+ if (processed)
+ *processed = size;
+ if (_mtProgresSpec)
+ _mtProgresSpec->AddOutSize(size);
return S_OK;
}
+
+class CSequentialOutMtNotify:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<ISequentialOutStream> _stream;
+ CMtEncMultiProgress *_mtProgresSpec;
+
+ CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)
+{
+ UInt32 realProcessed = 0;
+ HRESULT res = _stream->Write(data, size, &realProcessed);
+ if (processed)
+ *processed = realProcessed;
+ if (_mtProgresSpec)
+ _mtProgresSpec->AddOutSize(size);
+ return res;
+}
+
+
+
HRESULT CEncoder::Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
- const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ // const UInt64 *inStreamSize,
+ const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
@@ -151,27 +295,37 @@ HRESULT CEncoder::Encode(
{
RINOK(EncoderConstr());
- if (!_mixerCoderSpec)
+ if (!_mixerRef)
{
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
}
- _mixerCoderSpec->ReInit();
- // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
+
+ _mixer->ReInit();
+
+ CMtEncMultiProgress *mtProgressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> mtProgress;
+
+ CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
+ CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
- CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
+ CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
+
unsigned numMethods = _bindInfo.Coders.Size();
+
unsigned i;
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
iotb.Create();
iotb.InitWriting();
}
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
- CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
+ CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer);
@@ -179,94 +333,111 @@ HRESULT CEncoder::Encode(
}
for (i = 0; i < numMethods; i++)
- _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
+ _mixer->SetCoderInfo(i, NULL, NULL);
- if (_bindInfo.InStreams.IsEmpty())
- return E_FAIL;
- UInt32 mainCoderIndex, mainStreamIndex;
- _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
-
+
+ /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
+ But current BCJ2 encoder uses also another way to check exact size of current file.
+ So inStreamSize is not required. */
+
+ /*
if (inStreamSize)
- {
- CRecordVector<const UInt64 *> sizePointers;
- for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
- if (i == mainStreamIndex)
- sizePointers.Add(inStreamSize);
- else
- sizePointers.Add(NULL);
- _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
- }
+ _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
+ */
- // UInt64 outStreamStartPos;
- // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
-
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
inStreamSizeCountSpec->Init(inStream);
- CRecordVector<ISequentialInStream *> inStreamPointers;
+ ISequentialInStream *inStreamPointer = inStreamSizeCount;
CRecordVector<ISequentialOutStream *> outStreamPointers;
- inStreamPointers.Add(inStreamSizeCount);
- if (_bindInfo.OutStreams.Size() != 0)
- {
- outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
- outStreamSizeCount = outStreamSizeCountSpec;
- outStreamSizeCountSpec->SetStream(outStream);
- outStreamSizeCountSpec->Init();
- outStreamPointers.Add(outStreamSizeCount);
- }
+ SetFolder(folderItem);
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
- outStreamPointers.Add(tempBuffers[i - 1]);
-
- for (i = 0; i < _codersInfo.Size(); i++)
+ for (i = 0; i < numMethods; i++)
{
- CCoderInfo &encodingInfo = _codersInfo[i];
-
+ IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
+
CMyComPtr<ICryptoResetInitVector> resetInitVector;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
+ coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector)
{
resetInitVector->ResetInitVector();
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+ coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+
+ CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
+
if (writeCoderProperties)
{
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
- CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init();
- writeCoderProperties->WriteCoderProperties(outStream);
- outStreamSpec->CopyToBuffer(encodingInfo.Props);
+ writeCoderProperties->WriteCoderProperties(dynOutStream);
+ outStreamSpec->CopyToBuffer(props);
}
+ else
+ props.Free();
}
- UInt32 progressIndex = mainCoderIndex;
+ _mixer->SelectMainCoder(false);
+ UInt32 mainCoder = _mixer->MainCoderIndex;
- for (i = 0; i + 1 < _codersInfo.Size(); i++)
+ bool useMtProgress = false;
+ if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
{
- UInt64 m = _codersInfo[i].MethodID;
- if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
- progressIndex = i + 1;
+ #ifdef _7ZIP_ST
+ if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
+ #endif
+ useMtProgress = true;
}
- _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
+ if (useMtProgress)
+ {
+ mtProgressSpec = new CMtEncMultiProgress;
+ mtProgress = mtProgressSpec;
+ mtProgressSpec->Init(compressProgress);
+
+ mtOutStreamNotifySpec = new CSequentialOutMtNotify;
+ mtOutStreamNotify = mtOutStreamNotifySpec;
+ mtOutStreamNotifySpec->_stream = outStream;
+ mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
+
+ FOR_VECTOR(t, tempBufferSpecs)
+ {
+ tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec;
+ }
+ }
- RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
- &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
- ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
+ if (_bindInfo.PackStreams.Size() != 0)
+ {
+ outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
+ outStreamSizeCount = outStreamSizeCountSpec;
+ outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
+ outStreamSizeCountSpec->Init();
+ outStreamPointers.Add(outStreamSizeCount);
+ }
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
+ outStreamPointers.Add(tempBuffers[i - 1]);
+
+ RINOK(_mixer->Code(
+ &inStreamPointer,
+ &outStreamPointers.Front(),
+ mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
- if (_bindInfo.OutStreams.Size() != 0)
+ if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
RINOK(inOutTempBuffer.WriteToStream(outStream));
@@ -274,37 +445,45 @@ HRESULT CEncoder::Encode(
}
unpackSize = 0;
- for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
- int binder = _bindInfo.FindBinderForInStream(
- _bindReverseConverter->DestOutToSrcInMap[i]);
+ int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
UInt64 streamSize;
- if (binder < 0)
+ if (bond < 0)
{
streamSize = inStreamSizeCountSpec->GetSize();
unpackSize = streamSize;
}
else
- streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
+ streamSize = _mixer->GetBondStreamSize(bond);
coderUnpackSizes.Add(streamSize);
}
- for (i = 0; i < numMethods; i++)
- folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
+
return S_OK;
}
CEncoder::CEncoder(const CCompressionMethodMode &options):
- _bindReverseConverter(0),
- _constructed(false)
+ _constructed(false)
{
if (options.IsEmpty())
throw 1;
_options = options;
- _mixerCoderSpec = NULL;
+
+ #ifdef USE_MIXER_ST
+ _mixerST = NULL;
+ #endif
+
+ #ifdef USE_MIXER_MT
+ _mixerMT = NULL;
+ #endif
+
+ _mixer = NULL;
}
+
HRESULT CEncoder::EncoderConstr()
{
if (_constructed)
@@ -314,112 +493,125 @@ HRESULT CEncoder::EncoderConstr()
// it has only password method;
if (!_options.PasswordIsDefined)
throw 1;
- if (!_options.Binds.IsEmpty())
+ if (!_options.Bonds.IsEmpty())
throw 1;
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+
CMethodFull method;
-
- method.NumInStreams = 1;
- method.NumOutStreams = 1;
- coderStreamsInfo.NumInStreams = 1;
- coderStreamsInfo.NumOutStreams = 1;
method.Id = k_AES;
-
+ method.NumStreams = 1;
_options.Methods.Add(method);
+
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ coderStreamsInfo.NumStreams = 1;
_bindInfo.Coders.Add(coderStreamsInfo);
- _bindInfo.InStreams.Add(0);
- _bindInfo.OutStreams.Add(0);
+ _bindInfo.PackStreams.Add(0);
+ _bindInfo.UnpackCoder = 0;
}
else
{
- UInt32 numInStreams = 0, numOutStreams = 0;
+ UInt32 numOutStreams = 0;
unsigned i;
+
for (i = 0; i < _options.Methods.Size(); i++)
{
const CMethodFull &methodFull = _options.Methods[i];
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
- coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
- coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
- if (_options.Binds.IsEmpty())
+ NCoderMixer2::CCoderStreamsInfo cod;
+
+ cod.NumStreams = methodFull.NumStreams;
+
+ if (_options.Bonds.IsEmpty())
{
- if (i < _options.Methods.Size() - 1)
+ // if there are no bonds in options, we create bonds via first streams of coders
+ if (i != _options.Methods.Size() - 1)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
- bindPair.OutIndex = numOutStreams;
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond bond;
+ bond.PackIndex = numOutStreams;
+ bond.UnpackIndex = i + 1; // it's next coder
+ _bindInfo.Bonds.Add(bond);
}
- else if (coderStreamsInfo.NumOutStreams != 0)
- _bindInfo.OutStreams.Insert(0, numOutStreams);
- for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
- _bindInfo.OutStreams.Add(numOutStreams + j);
+ else if (cod.NumStreams != 0)
+ _bindInfo.PackStreams.Insert(0, numOutStreams);
+
+ for (UInt32 j = 1; j < cod.NumStreams; j++)
+ _bindInfo.PackStreams.Add(numOutStreams + j);
}
- numInStreams += coderStreamsInfo.NumInStreams;
- numOutStreams += coderStreamsInfo.NumOutStreams;
+ numOutStreams += cod.NumStreams;
- _bindInfo.Coders.Add(coderStreamsInfo);
+ _bindInfo.Coders.Add(cod);
}
- if (!_options.Binds.IsEmpty())
+ if (!_options.Bonds.IsEmpty())
{
- for (i = 0; i < _options.Binds.Size(); i++)
+ for (i = 0; i < _options.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair bindPair;
- const CBind &bind = _options.Binds[i];
- bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
- bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond mixerBond;
+ const CBond2 &bond = _options.Bonds[i];
+ if (bond.InCoder >= _bindInfo.Coders.Size()
+ || bond.OutCoder >= _bindInfo.Coders.Size()
+ || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
+ return E_INVALIDARG;
+ mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
+ mixerBond.UnpackIndex = bond.InCoder;
+ _bindInfo.Bonds.Add(mixerBond);
}
- for (i = 0; i < (int)numOutStreams; i++)
- if (_bindInfo.FindBinderForOutStream(i) == -1)
- _bindInfo.OutStreams.Add(i);
+
+ for (i = 0; i < numOutStreams; i++)
+ if (_bindInfo.FindBond_for_PackStream(i) == -1)
+ _bindInfo.PackStreams.Add(i);
}
- for (i = 0; i < (int)numInStreams; i++)
- if (_bindInfo.FindBinderForInStream(i) == -1)
- _bindInfo.InStreams.Add(i);
+ if (!_bindInfo.SetUnpackCoder())
+ return E_INVALIDARG;
- if (_bindInfo.InStreams.IsEmpty())
- throw 1; // this is error
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
- // Make main stream first in list
- int inIndex = _bindInfo.InStreams[0];
- for (;;)
+ if (_bindInfo.PackStreams.Size() != 1)
{
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
- UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
- int binder = _bindInfo.FindBinderForOutStream(outIndex);
- if (binder >= 0)
+ /* main_PackStream is pack stream of main path of coders tree.
+ We find main_PackStream, and place to start of list of out streams.
+ It allows to use more optimal memory usage for temp buffers,
+ if main_PackStream is largest stream. */
+
+ UInt32 ci = _bindInfo.UnpackCoder;
+
+ for (;;)
{
- inIndex = _bindInfo.BindPairs[binder].InIndex;
- continue;
- }
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
- if (_bindInfo.OutStreams[i] == outIndex)
- {
- _bindInfo.OutStreams.Delete(i);
- _bindInfo.OutStreams.Insert(0, outIndex);
+ if (_bindInfo.Coders[ci].NumStreams == 0)
break;
+
+ UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
+ int bond = _bindInfo.FindBond_for_PackStream(outIndex);
+ if (bond >= 0)
+ {
+ ci = _bindInfo.Bonds[bond].UnpackIndex;
+ continue;
}
- break;
+
+ int si = _bindInfo.FindStream_in_PackStreams(outIndex);
+ if (si >= 0)
+ _bindInfo.PackStreams.MoveToFront(si);
+ break;
+ }
}
if (_options.PasswordIsDefined)
{
- unsigned numCryptoStreams = _bindInfo.OutStreams.Size();
+ unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
+ unsigned numInStreams = _bindInfo.Coders.Size();
+
for (i = 0; i < numCryptoStreams; i++)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = numInStreams + i;
- bindPair.OutIndex = _bindInfo.OutStreams[i];
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond bond;
+ bond.UnpackIndex = numInStreams + i;
+ bond.PackIndex = _bindInfo.PackStreams[i];
+ _bindInfo.Bonds.Add(bond);
}
- _bindInfo.OutStreams.Clear();
+ _bindInfo.PackStreams.Clear();
/*
if (numCryptoStreams == 0)
@@ -428,37 +620,37 @@ HRESULT CEncoder::EncoderConstr()
for (i = 0; i < numCryptoStreams; i++)
{
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method;
- method.NumInStreams = 1;
- method.NumOutStreams = 1;
- coderStreamsInfo.NumInStreams = method.NumOutStreams;
- coderStreamsInfo.NumOutStreams = method.NumInStreams;
+ method.NumStreams = 1;
method.Id = k_AES;
-
_options.Methods.Add(method);
- _bindInfo.Coders.Add(coderStreamsInfo);
- _bindInfo.OutStreams.Add(numOutStreams + i);
+
+ NCoderMixer2::CCoderStreamsInfo cod;
+ cod.NumStreams = 1;
+ _bindInfo.Coders.Add(cod);
+
+ _bindInfo.PackStreams.Add(numOutStreams++);
}
}
}
- for (int i = _options.Methods.Size() - 1; i >= 0; i--)
- {
- const CMethodFull &methodFull = _options.Methods[i];
- _decompressionMethods.Add(methodFull.Id);
- }
+ for (unsigned i = _options.Methods.Size(); i != 0;)
+ _decompressionMethods.Add(_options.Methods[--i].Id);
- _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
- _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
+ if (_bindInfo.Coders.Size() > 16)
+ return E_INVALIDARG;
+ if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
+ return E_INVALIDARG;
+
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
+
+ InitBindConv();
_constructed = true;
return S_OK;
}
-CEncoder::~CEncoder()
-{
- delete _bindReverseConverter;
-}
+CEncoder::~CEncoder() {}
}}
diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
index 0f28cfb..434cbec 100644
--- a/CPP/7zip/Archive/7z/7zEncode.h
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -3,47 +3,82 @@
#ifndef __7Z_ENCODE_H
#define __7Z_ENCODE_H
-// #include "../../Common/StreamObjects.h"
-
#include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h"
-#include "../Common/CoderMixer2MT.h"
-#ifdef _ST_MODE
-#include "../Common/CoderMixer2ST.h"
-#endif
-#include "7zItem.h"
-#include "../../Common/CreateCoder.h"
+#include "7zItem.h"
namespace NArchive {
namespace N7z {
-class CEncoder
+class CMtEncMultiProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
- CMyComPtr<ICompressCoder2> _mixerCoder;
+ CMyComPtr<ICompressProgressInfo> _progress;
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
+ #endif
+
+public:
+ UInt64 OutSize;
+
+ CMtEncMultiProgress(): OutSize(0) {}
+
+ void Init(ICompressProgressInfo *progress);
- CObjectVector<CCoderInfo> _codersInfo;
+ void AddOutSize(UInt64 addOutSize)
+ {
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+ #endif
+ OutSize += addOutSize;
+ }
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+class CEncoder
+{
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
+ #endif
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
CCompressionMethodMode _options;
- NCoderMixer::CBindInfo _bindInfo;
- NCoderMixer::CBindInfo _decompressBindInfo;
- NCoderMixer::CBindReverseConverter *_bindReverseConverter;
+ NCoderMixer2::CBindInfo _bindInfo;
CRecordVector<CMethodId> _decompressionMethods;
+ CRecordVector<UInt32> _SrcIn_to_DestOut;
+ CRecordVector<UInt32> _SrcOut_to_DestIn;
+ // CRecordVector<UInt32> _DestIn_to_SrcOut;
+ CRecordVector<UInt32> _DestOut_to_SrcIn;
+
+ void InitBindConv();
+ void SetFolder(CFolder &folder);
+
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce);
bool _constructed;
public:
+
CEncoder(const CCompressionMethodMode &options);
~CEncoder();
HRESULT EncoderConstr();
HRESULT Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
- const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ // const UInt64 *inStreamSize,
+ const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 9310762..a675797 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -2,204 +2,336 @@
#include "StdAfx.h"
+#include "../../../../C/7zCrc.h"
+
#include "../../../Common/ComTry.h"
#include "../../Common/ProgressUtils.h"
#include "7zDecode.h"
-// #include "7z1Decode.h"
-#include "7zFolderOutStream.h"
#include "7zHandler.h"
+// EXTERN_g_ExternalCodecs
+
namespace NArchive {
namespace N7z {
-struct CExtractFolderInfo
+class CFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
{
- #ifdef _7Z_VOL
- int VolumeIndex;
- #endif
- CNum FileIndex;
- CNum FolderIndex;
- CBoolVector ExtractStatuses;
- UInt64 UnpackSize;
- CExtractFolderInfo(
- #ifdef _7Z_VOL
- int volumeIndex,
- #endif
- CNum fileIndex, CNum folderIndex):
- #ifdef _7Z_VOL
- VolumeIndex(volumeIndex),
- #endif
- FileIndex(fileIndex),
- FolderIndex(folderIndex),
- UnpackSize(0)
+ CMyComPtr<ISequentialOutStream> _stream;
+public:
+ bool TestMode;
+ bool CheckCrc;
+private:
+ bool _fileIsOpen;
+ bool _calcCrc;
+ UInt32 _crc;
+ UInt64 _rem;
+
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _fileIndex;
+
+ HRESULT OpenFile(bool isCorrupted = false);
+ HRESULT CloseFile_and_SetResult(Int32 res);
+ HRESULT CloseFile();
+ HRESULT ProcessEmptyFiles();
+
+public:
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ const CDbEx *_db;
+ CMyComPtr<IArchiveExtractCallback> ExtractCallback;
+
+ bool ExtraWriteWasCut;
+
+ CFolderOutStream():
+ TestMode(false),
+ CheckCrc(true)
+ {}
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+
+ HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);
+ HRESULT FlushCorrupted(Int32 callbackOperationResult);
+
+ bool WasWritingFinished() const { return _numFiles == 0; }
+};
+
+
+HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)
+{
+ _fileIndex = startIndex;
+ _indexes = indexes;
+ _numFiles = numFiles;
+
+ _fileIsOpen = false;
+ ExtraWriteWasCut = false;
+
+ return ProcessEmptyFiles();
+}
+
+HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
+{
+ const CFileItem &fi = _db->Files[_fileIndex];
+ UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);
+ Int32 askMode = (_fileIndex == nextFileIndex) ?
+ (TestMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+
+ if (isCorrupted
+ && askMode == NExtract::NAskMode::kExtract
+ && !_db->IsItemAnti(_fileIndex)
+ && !fi.IsDir)
+ askMode = NExtract::NAskMode::kTest;
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode));
+
+ _stream = realOutStream;
+ _crc = CRC_INIT_VAL;
+ _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);
+
+ _fileIsOpen = true;
+ _rem = fi.Size;
+
+ if (askMode == NExtract::NAskMode::kExtract
+ && !realOutStream
+ && !_db->IsItemAnti(_fileIndex)
+ && !fi.IsDir)
+ askMode = NExtract::NAskMode::kSkip;
+ return ExtractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)
+{
+ _stream.Release();
+ _fileIsOpen = false;
+
+ if (!_indexes)
+ _numFiles--;
+ else if (*_indexes == _fileIndex)
+ {
+ _indexes++;
+ _numFiles--;
+ }
+
+ _fileIndex++;
+ return ExtractCallback->SetOperationResult(res);
+}
+
+HRESULT CFolderOutStream::CloseFile()
+{
+ const CFileItem &fi = _db->Files[_fileIndex];
+ return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?
+ NExtract::NOperationResult::kOK :
+ NExtract::NOperationResult::kCRCError);
+}
+
+HRESULT CFolderOutStream::ProcessEmptyFiles()
+{
+ while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)
{
- if (fileIndex != kNumNoIndex)
+ RINOK(OpenFile());
+ RINOK(CloseFile());
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
{
- ExtractStatuses.ClearAndSetSize(1);
- ExtractStatuses[0] = true;
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ if (processedSize)
+ *processedSize += cur;
+ data = (const Byte *)data + cur;
+ size -= cur;
+ _rem -= cur;
+ if (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
+ }
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
}
- };
-};
+
+ RINOK(ProcessEmptyFiles());
+ if (_numFiles == 0)
+ {
+ // we support partial extracting
+ /*
+ if (processedSize)
+ *processedSize += size;
+ break;
+ */
+ ExtraWriteWasCut = true;
+ // return S_FALSE;
+ return k_My_HRESULT_WritingWasCut;
+ }
+ RINOK(OpenFile());
+ }
+
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
+{
+ while (_numFiles != 0)
+ {
+ if (_fileIsOpen)
+ {
+ RINOK(CloseFile_and_SetResult(callbackOperationResult));
+ }
+ else
+ {
+ RINOK(OpenFile(true));
+ }
+ }
+ return S_OK;
+}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{
COM_TRY_BEGIN
- bool testMode = (testModeSpec != 0);
+
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+
UInt64 importantTotalUnpacked = 0;
+ // numItems = (UInt32)(Int32)-1;
+
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
- numItems =
- #ifdef _7Z_VOL
- _refs.Size();
- #else
- _db.Files.Size();
- #endif
+ numItems = _db.Files.Size();
- if(numItems == 0)
+ if (numItems == 0)
return S_OK;
- /*
- if(_volumes.Size() != 1)
- return E_FAIL;
- const CVolume &volume = _volumes.Front();
- const CDbEx &_db = volume.Database;
- IInStream *_inStream = volume.Stream;
- */
-
- CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
- for (UInt32 ii = 0; ii < numItems; ii++)
{
- // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
- UInt32 ref2Index = allFilesMode ? ii : indices[ii];
- // const CRef2 &ref2 = _refs[ref2Index];
-
- // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
+ CNum prevFolder = kNumNoIndex;
+ UInt32 nextFile = 0;
+
+ UInt32 i;
+
+ for (i = 0; i < numItems; i++)
{
- #ifdef _7Z_VOL
- // const CRef &ref = ref2.Refs[ri];
- const CRef &ref = _refs[ref2Index];
-
- int volumeIndex = ref.VolumeIndex;
- const CVolume &volume = _volumes[volumeIndex];
- const CDbEx &db = volume.Database;
- UInt32 fileIndex = ref.ItemIndex;
- #else
- const CDbEx &db = _db;
- UInt32 fileIndex = ref2Index;
- #endif
-
- CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
if (folderIndex == kNumNoIndex)
- {
- extractFolderInfoVector.Add(CExtractFolderInfo(
- #ifdef _7Z_VOL
- volumeIndex,
- #endif
- fileIndex, kNumNoIndex));
continue;
- }
- if (extractFolderInfoVector.IsEmpty() ||
- folderIndex != extractFolderInfoVector.Back().FolderIndex
- #ifdef _7Z_VOL
- || volumeIndex != extractFolderInfoVector.Back().VolumeIndex
- #endif
- )
- {
- extractFolderInfoVector.Add(CExtractFolderInfo(
- #ifdef _7Z_VOL
- volumeIndex,
- #endif
- kNumNoIndex, folderIndex));
- UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);
- importantTotalUnpacked += unpackSize;
- extractFolderInfoVector.Back().UnpackSize = unpackSize;
- }
-
- CExtractFolderInfo &efi = extractFolderInfoVector.Back();
-
- // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
- CNum startIndex = db.FolderStartFileIndex[folderIndex];
- for (CNum index = efi.ExtractStatuses.Size();
- index <= fileIndex - startIndex; index++)
- {
- // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;
- // Count partial_folder_size
- // efi.UnpackSize += unpackSize;
- // importantTotalUnpacked += unpackSize;
- efi.ExtractStatuses.Add(index == fileIndex - startIndex);
- }
+ if (folderIndex != prevFolder || fileIndex < nextFile)
+ nextFile = _db.FolderStartFileIndex[folderIndex];
+ for (CNum index = nextFile; index <= fileIndex; index++)
+ importantTotalUnpacked += _db.Files[index].Size;
+ nextFile = fileIndex + 1;
+ prevFolder = folderIndex;
}
}
RINOK(extractCallback->SetTotal(importantTotalUnpacked));
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
CDecoder decoder(
- #ifdef _ST_MODE
- false
+ #if !defined(USE_MIXER_MT)
+ false
+ #elif !defined(USE_MIXER_ST)
+ true
+ #elif !defined(__7Z_SET_PROPERTIES)
+ #ifdef _7ZIP_ST
+ false
+ #else
+ true
+ #endif
#else
- true
+ _useMultiThreadMixer
#endif
);
- // CDecoder1 decoder;
- UInt64 totalPacked = 0;
- UInt64 totalUnpacked = 0;
UInt64 curPacked, curUnpacked;
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> progress = lps;
- lps->Init(extractCallback, false);
+ CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
+ extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
+
+ CFolderOutStream *folderOutStream = new CFolderOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
- for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
+ folderOutStream->_db = &_db;
+ folderOutStream->ExtractCallback = extractCallback;
+ folderOutStream->TestMode = (testModeSpec != 0);
+ folderOutStream->CheckCrc = (_crcSize != 0);
+
+ for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
{
- lps->OutSize = totalUnpacked;
- lps->InSize = totalPacked;
RINOK(lps->SetCur());
- if (i >= extractFolderInfoVector.Size())
+ if (i >= numItems)
break;
-
- const CExtractFolderInfo &efi = extractFolderInfoVector[i];
- curUnpacked = efi.UnpackSize;
+
+ curUnpacked = 0;
curPacked = 0;
- CFolderOutStream *folderOutStream = new CFolderOutStream;
- CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
- #ifdef _7Z_VOL
- const CVolume &volume = _volumes[efi.VolumeIndex];
- const CDbEx &db = volume.Database;
- #else
- const CDbEx &db = _db;
- #endif
+ UInt32 numSolidFiles = 1;
- CNum startIndex;
- if (efi.FileIndex != kNumNoIndex)
- startIndex = efi.FileIndex;
- else
- startIndex = db.FolderStartFileIndex[efi.FolderIndex];
+ if (folderIndex != kNumNoIndex)
+ {
+ curPacked = _db.GetFolderFullPackSize(folderIndex);
+ UInt32 nextFile = fileIndex + 1;
+ fileIndex = _db.FolderStartFileIndex[folderIndex];
+ UInt32 k;
- HRESULT result = folderOutStream->Init(&db,
- #ifdef _7Z_VOL
- volume.StartRef2Index,
- #else
- 0,
- #endif
- startIndex,
- &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
+ for (k = i + 1; k < numItems; k++)
+ {
+ UInt32 fileIndex2 = allFilesMode ? k : indices[k];
+ if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex
+ || fileIndex2 < nextFile)
+ break;
+ nextFile = fileIndex2 + 1;
+ }
+
+ numSolidFiles = k - i;
+
+ for (k = fileIndex; k < nextFile; k++)
+ curUnpacked += _db.Files[k].Size;
+ }
+
+ {
+ HRESULT result = folderOutStream->Init(fileIndex,
+ allFilesMode ? NULL : indices + i,
+ numSolidFiles);
- RINOK(result);
+ i += numSolidFiles;
- if (efi.FileIndex != kNumNoIndex)
- continue;
+ RINOK(result);
+ }
- CNum folderIndex = efi.FolderIndex;
- curPacked = _db.GetFolderFullPackSize(folderIndex);
+ // to test solid block with zero unpacked size we disable that code
+ if (folderOutStream->WasWritingFinished())
+ continue;
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
@@ -212,50 +344,64 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
+ UString password;
#endif
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
- #ifdef _7Z_VOL
- volume.Stream,
- #else
- _inStream,
- #endif
- db.ArcInfo.DataStartPosition,
- db, folderIndex,
+ _inStream,
+ _db.ArcInfo.DataStartPosition,
+ _db, folderIndex,
+ &curUnpacked,
+
outStream,
- progress
+ progress,
+ NULL // *inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX)
, true, _numThreads
#endif
);
- if (result == S_FALSE)
+ if (result == S_FALSE || result == E_NOTIMPL)
{
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
- }
- if (result == E_NOTIMPL)
- {
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));
+ bool wasFinished = folderOutStream->WasWritingFinished();
+
+ int resOp = (result == S_FALSE ?
+ NExtract::NOperationResult::kDataError :
+ NExtract::NOperationResult::kUnsupportedMethod);
+
+ RINOK(folderOutStream->FlushCorrupted(resOp));
+
+ if (wasFinished)
+ {
+ // we don't show error, if it's after required files
+ if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)
+ {
+ RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp));
+ }
+ }
continue;
}
+
if (result != S_OK)
return result;
- if (folderOutStream->WasWritingFinished() != S_OK)
- {
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
- }
+
+ RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
+ continue;
}
catch(...)
{
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
+ // continue;
+ return E_FAIL;
}
}
+
return S_OK;
+
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 7971191..51a6f68 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -7,96 +7,103 @@
namespace NArchive {
namespace N7z {
-CFolderInStream::CFolderInStream()
-{
- _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
- _inStreamWithHash = _inStreamWithHashSpec;
-}
-
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
- const UInt32 *fileIndices, UInt32 numFiles)
+ const UInt32 *indexes, unsigned numFiles)
{
_updateCallback = updateCallback;
+ _indexes = indexes;
_numFiles = numFiles;
- _fileIndex = 0;
- _fileIndices = fileIndices;
- Processed.Clear();
- CRCs.Clear();
- Sizes.Clear();
- _fileIsOpen = false;
- _currentSizeIsDefined = false;
+ _index = 0;
+
+ Processed.ClearAndReserve(numFiles);
+ CRCs.ClearAndReserve(numFiles);
+ Sizes.ClearAndReserve(numFiles);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ _stream.Release();
}
HRESULT CFolderInStream::OpenStream()
{
- _filePos = 0;
- while (_fileIndex < _numFiles)
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ while (_index < _numFiles)
{
CMyComPtr<ISequentialInStream> stream;
- HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
- if (result != S_OK && result != S_FALSE)
- return result;
- _fileIndex++;
- _inStreamWithHashSpec->SetStream(stream);
- _inStreamWithHashSpec->Init();
+ HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
+ if (result != S_OK)
+ {
+ if (result != S_FALSE)
+ return result;
+ }
+
+ _stream = stream;
+
if (stream)
{
- _fileIsOpen = true;
CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize)
{
- RINOK(streamGetSize->GetSize(&_currentSize));
- _currentSizeIsDefined = true;
+ if (streamGetSize->GetSize(&_size) == S_OK)
+ _size_Defined = true;
}
return S_OK;
}
+
+ _index++;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- Sizes.Add(0);
- Processed.Add(result == S_OK);
- AddDigest();
+ AddFileInfo(result == S_OK);
}
return S_OK;
}
-void CFolderInStream::AddDigest()
+void CFolderInStream::AddFileInfo(bool isProcessed)
{
- CRCs.Add(_inStreamWithHashSpec->GetCRC());
-}
-
-HRESULT CFolderInStream::CloseStream()
-{
- RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- _inStreamWithHashSpec->ReleaseStream();
- _fileIsOpen = false;
- _currentSizeIsDefined = false;
- Processed.Add(true);
- Sizes.Add(_filePos);
- AddDigest();
- return S_OK;
+ Processed.Add(isProcessed);
+ Sizes.Add(_pos);
+ CRCs.Add(CRC_GET_DIGEST(_crc));
}
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != 0)
+ if (processedSize)
*processedSize = 0;
- while (size > 0)
+ while (size != 0)
{
- if (_fileIsOpen)
+ if (_stream)
{
UInt32 processed2;
- RINOK(_inStreamWithHash->Read(data, size, &processed2));
- if (processed2 == 0)
+ RINOK(_stream->Read(data, size, &processed2));
+ if (processed2 != 0)
{
- RINOK(CloseStream());
- continue;
+ _crc = CrcUpdate(_crc, data, processed2);
+ _pos += processed2;
+ if (processedSize)
+ *processedSize = processed2;
+ return S_OK;
}
- if (processedSize != 0)
- *processedSize = processed2;
- _filePos += processed2;
- break;
+
+ _stream.Release();
+ _index++;
+ AddFileInfo(true);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
- if (_fileIndex >= _numFiles)
+
+ if (_index >= _numFiles)
break;
RINOK(OpenStream());
}
@@ -106,17 +113,23 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
- unsigned index2 = (unsigned)subStream;
if (subStream > Sizes.Size())
- return E_FAIL;
- if (index2 < Sizes.Size())
+ return S_FALSE; // E_FAIL;
+
+ unsigned index = (unsigned)subStream;
+ if (index < Sizes.Size())
{
- *value = Sizes[index2];
+ *value = Sizes[index];
return S_OK;
}
- if (!_currentSizeIsDefined)
+
+ if (!_size_Defined)
+ {
+ *value = _pos;
return S_FALSE;
- *value = _currentSize;
+ }
+
+ *value = (_pos > _size ? _pos : _size);
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
index e516dff..f2b1c59 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -3,11 +3,13 @@
#ifndef __7Z_FOLDER_IN_STREAM_H
#define __7Z_FOLDER_IN_STREAM_H
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyVector.h"
+
#include "../../ICoder.h"
#include "../IArchive.h"
-#include "../Common/InStreamWithCRC.h"
-
-#include "7zItem.h"
namespace NArchive {
namespace N7z {
@@ -17,33 +19,34 @@ class CFolderInStream:
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
- CSequentialInStreamWithCRC *_inStreamWithHashSpec;
- CMyComPtr<ISequentialInStream> _inStreamWithHash;
- CMyComPtr<IArchiveUpdateCallback> _updateCallback;
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _pos;
+ UInt32 _crc;
+ bool _size_Defined;
+ UInt64 _size;
- bool _currentSizeIsDefined;
- bool _fileIsOpen;
- UInt64 _currentSize;
- UInt64 _filePos;
- const UInt32 *_fileIndices;
- UInt32 _numFiles;
- UInt32 _fileIndex;
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _index;
+
+ CMyComPtr<IArchiveUpdateCallback> _updateCallback;
HRESULT OpenStream();
- HRESULT CloseStream();
- void AddDigest();
+ void AddFileInfo(bool isProcessed);
public:
CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes;
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
- CFolderInStream();
- void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
+ void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
+
+ bool WasFinished() const { return _index == _numFiles; }
+
UInt64 GetFullSize() const
{
UInt64 size = 0;
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
deleted file mode 100644
index d206d7c..0000000
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// 7zFolderOutStream.cpp
-
-#include "StdAfx.h"
-
-#include "7zFolderOutStream.h"
-
-namespace NArchive {
-namespace N7z {
-
-CFolderOutStream::CFolderOutStream()
-{
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
-}
-
-HRESULT CFolderOutStream::Init(
- const CDbEx *db,
- UInt32 ref2Offset, UInt32 startIndex,
- const CBoolVector *extractStatuses,
- IArchiveExtractCallback *extractCallback,
- bool testMode, bool checkCrc)
-{
- _db = db;
- _ref2Offset = ref2Offset;
- _startIndex = startIndex;
-
- _extractStatuses = extractStatuses;
- _extractCallback = extractCallback;
- _testMode = testMode;
- _checkCrc = checkCrc;
-
- _currentIndex = 0;
- _fileIsOpen = false;
- return ProcessEmptyFiles();
-}
-
-HRESULT CFolderOutStream::OpenFile()
-{
- Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
- NExtract::NAskMode::kTest :
- NExtract::NAskMode::kExtract) :
- NExtract::NAskMode::kSkip;
- CMyComPtr<ISequentialOutStream> realOutStream;
- UInt32 index = _startIndex + _currentIndex;
- RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
- _crcStreamSpec->SetStream(realOutStream);
- _crcStreamSpec->Init(_checkCrc);
- _fileIsOpen = true;
- const CFileItem &fi = _db->Files[index];
- _rem = fi.Size;
- if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&
- !_db->IsItemAnti(index) && !fi.IsDir)
- askMode = NExtract::NAskMode::kSkip;
- return _extractCallback->PrepareOperation(askMode);
-}
-
-HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
-{
- _crcStreamSpec->ReleaseStream();
- _fileIsOpen = false;
- _currentIndex++;
- return _extractCallback->SetOperationResult(res);
-}
-
-HRESULT CFolderOutStream::CloseFileAndSetResult()
-{
- const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
- return CloseFileAndSetResult(
- (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
- NExtract::NOperationResult::kOK :
- NExtract::NOperationResult::kCRCError);
-}
-
-HRESULT CFolderOutStream::ProcessEmptyFiles()
-{
- while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
- {
- RINOK(OpenFile());
- RINOK(CloseFileAndSetResult());
- }
- return S_OK;
-}
-
-STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != NULL)
- *processedSize = 0;
- while (size != 0)
- {
- if (_fileIsOpen)
- {
- UInt32 cur = size < _rem ? size : (UInt32)_rem;
- RINOK(_crcStream->Write(data, cur, &cur));
- if (cur == 0)
- break;
- data = (const Byte *)data + cur;
- size -= cur;
- _rem -= cur;
- if (processedSize != NULL)
- *processedSize += cur;
- if (_rem == 0)
- {
- RINOK(CloseFileAndSetResult());
- RINOK(ProcessEmptyFiles());
- continue;
- }
- }
- else
- {
- RINOK(ProcessEmptyFiles());
- if (_currentIndex == _extractStatuses->Size())
- {
- // we support partial extracting
- if (processedSize != NULL)
- *processedSize += size;
- break;
- }
- RINOK(OpenFile());
- }
- }
- return S_OK;
-}
-
-STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
-{
- *value = 0;
- if ((int)subStream >= _extractStatuses->Size())
- return S_FALSE;
- *value = _db->Files[_startIndex + (int)subStream].Size;
- return S_OK;
-}
-
-HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
-{
- while (_currentIndex < _extractStatuses->Size())
- {
- if (_fileIsOpen)
- {
- RINOK(CloseFileAndSetResult(resultEOperationResult));
- }
- else
- {
- RINOK(OpenFile());
- }
- }
- return S_OK;
-}
-
-}}
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
deleted file mode 100644
index c00aba7..0000000
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 7zFolderOutStream.h
-
-#ifndef __7Z_FOLDER_OUT_STREAM_H
-#define __7Z_FOLDER_OUT_STREAM_H
-
-#include "../../IStream.h"
-#include "../IArchive.h"
-#include "../Common/OutStreamWithCRC.h"
-
-#include "7zIn.h"
-
-namespace NArchive {
-namespace N7z {
-
-class CFolderOutStream:
- public ISequentialOutStream,
- public ICompressGetSubStreamSize,
- public CMyUnknownImp
-{
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
- const CDbEx *_db;
- const CBoolVector *_extractStatuses;
- CMyComPtr<IArchiveExtractCallback> _extractCallback;
- UInt32 _ref2Offset;
- UInt32 _startIndex;
- unsigned _currentIndex;
- bool _testMode;
- bool _checkCrc;
- bool _fileIsOpen;
- UInt64 _rem;
-
- HRESULT OpenFile();
- HRESULT CloseFileAndSetResult(Int32 res);
- HRESULT CloseFileAndSetResult();
- HRESULT ProcessEmptyFiles();
-public:
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
-
- CFolderOutStream();
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
-
- HRESULT Init(
- const CDbEx *db,
- UInt32 ref2Offset, UInt32 startIndex,
- const CBoolVector *extractStatuses,
- IArchiveExtractCallback *extractCallback,
- bool testMode, bool checkCrc);
- HRESULT FlushCorrupted(Int32 resultEOperationResult);
- HRESULT WasWritingFinished() const
- { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
-};
-
-}}
-
-#endif
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index 6104440..ce955a6 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -36,10 +36,14 @@ CHandler::CHandler()
#endif
#ifdef EXTRACT_ONLY
+
_crcSize = 4;
+
#ifdef __7Z_SET_PROPERTIES
_numThreads = NSystem::GetNumberOfProcessors();
+ _useMultiThreadMixer = true;
#endif
+
#endif
}
@@ -150,22 +154,12 @@ static char *AddProp32(char *s, const char *name, UInt32 v)
void CHandler::AddMethodName(AString &s, UInt64 id)
{
- UString methodName;
- FindMethod(EXTERNAL_CODECS_VARS id, methodName);
- if (methodName.IsEmpty())
- {
- for (unsigned i = 0; i < methodName.Len(); i++)
- if (methodName[i] >= 0x80)
- {
- methodName.Empty();
- break;
- }
- }
- if (methodName.IsEmpty())
+ AString name;
+ FindMethod(EXTERNAL_CODECS_VARS id, name);
+ if (name.IsEmpty())
ConvertMethodIdToString(s, id);
else
- for (unsigned i = 0; i < methodName.Len(); i++)
- s += (char)methodName[i];
+ s += name;
}
#endif
@@ -186,8 +180,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
FOR_VECTOR (i, pm.IDs)
{
UInt64 id = pm.IDs[i];
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
char temp[16];
if (id == k_LZMA2)
{
@@ -376,6 +369,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
// numCoders == 0 ???
CNum numCoders = inByte.ReadNum();
bool needSpace = false;
+
for (; numCoders != 0; numCoders--, needSpace = true)
{
if (pos < 32) // max size of property
@@ -435,11 +429,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
name = "LZMA2";
if (propsSize == 1)
{
- Byte p = props[0];
- if ((p & 1) == 0)
- ConvertUInt32ToString((UInt32)((p >> 1) + 12), s);
+ Byte d = props[0];
+ if ((d & 1) == 0)
+ ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
else
- GetStringForSizeValue(s, 3 << ((p >> 1) + 11));
+ GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
}
}
else if (id == k_PPMD)
@@ -500,17 +494,8 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
}
else
{
- UString methodName;
+ AString methodName;
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
- if (methodName.IsEmpty())
- {
- for (unsigned j = 0; j < methodName.Len(); j++)
- if (methodName[j] >= 0x80)
- {
- methodName.Empty();
- break;
- }
- }
if (needSpace)
temp[--pos] = ' ';
if (methodName.IsEmpty())
@@ -522,10 +507,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
break;
pos -= len;
for (unsigned i = 0; i < len; i++)
- temp[pos + i] = (char)methodName[i];
+ temp[pos + i] = methodName[i];
}
}
}
+
if (numCoders != 0 && pos >= 4)
{
temp[--pos] = ' ';
@@ -533,6 +519,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
temp[--pos] = '.';
temp[--pos] = '.';
}
+
return PropVarEm_Set_Str(prop, temp + pos);
// }
}
@@ -555,7 +542,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CFileItem &item = _db.Files[index];
UInt32 index2 = index;
- switch(propID)
+ switch (propID)
{
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
case kpidSize:
@@ -608,7 +595,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
*/
case kpidPath: return _db.GetPath_Prop(index, value);
+
#ifndef _SFX
+
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
case kpidBlock:
{
@@ -617,30 +606,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
}
break;
+ /*
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
- /*
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
- const CFolder &folderInfo = _db.Folders[folderIndex];
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
- folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+ _db.FoStartPackStreamIndex[folderIndex + 1] -
+ _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
{
- prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+ PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
}
- else
- prop = (UInt64)0;
}
else
- prop = (UInt64)0;
- */
+ PropVarEm_Set_UInt64(value, 0);
}
break;
+ */
+
#endif
}
// prop.Detach(value);
@@ -668,7 +656,13 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
- CInArchive archive;
+ CInArchive archive(
+ #ifdef __7Z_SET_PROPERTIES
+ _useMultiThreadMixer
+ #else
+ true
+ #endif
+ );
_db.IsArc = false;
RINOK(archive.Open(stream, maxCheckStartPosition));
_db.IsArc = true;
@@ -677,7 +671,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
EXTERNAL_CODECS_VARS
_db
#ifndef _NO_CRYPTO
- , getTextPassword, _isEncrypted, _passwordIsDefined
+ , getTextPassword, _isEncrypted, _passwordIsDefined, _password
#endif
);
RINOK(result);
@@ -688,8 +682,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
{
Close();
// return E_INVALIDARG;
+ // return S_FALSE;
// we must return out_of_memory here
- return S_FALSE;
+ return E_OUTOFMEMORY;
}
// _inStream = stream;
#ifndef _SFX
@@ -707,6 +702,7 @@ STDMETHODIMP CHandler::Close()
#ifndef _NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
+ _password.Empty();
#endif
return S_OK;
COM_TRY_END
@@ -715,11 +711,12 @@ STDMETHODIMP CHandler::Close()
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
+ _useMultiThreadMixer = true;
for (UInt32 i = 0; i < numProps; i++)
{
@@ -729,10 +726,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return E_INVALIDARG;
const PROPVARIANT &value = values[i];
UInt32 number;
- int index = ParseStringToUInt32(name, number);
+ unsigned index = ParseStringToUInt32(name, number);
if (index == 0)
{
- if (name.IsPrefixedBy(L"mt"))
+ if (name.IsEqualTo("mtf"))
+ {
+ RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
+ continue;
+ }
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
continue;
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index e7a80d8..00a8e83 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -18,24 +18,14 @@
namespace NArchive {
namespace N7z {
-const UInt32 k_Copy = 0x0;
-const UInt32 k_Delta = 3;
-const UInt32 k_LZMA2 = 0x21;
-const UInt32 k_LZMA = 0x030101;
-const UInt32 k_PPMD = 0x030401;
-const UInt32 k_BCJ = 0x03030103;
-const UInt32 k_BCJ2 = 0x0303011B;
-const UInt32 k_Deflate = 0x040108;
-const UInt32 k_BZip2 = 0x040202;
-
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
-#if !defined(_7ZIP_ST) && !defined(_SFX)
-#define __7Z_SET_PROPERTIES
-#endif
+ #if !defined(_7ZIP_ST) && !defined(_SFX)
+ #define __7Z_SET_PROPERTIES
+ #endif
#else
-#define __7Z_SET_PROPERTIES
+ #define __7Z_SET_PROPERTIES
#endif
#endif
@@ -54,6 +44,7 @@ public:
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
+ bool _useTypeSorting;
bool _compressHeaders;
bool _encryptHeadersSpecified;
@@ -64,7 +55,9 @@ public:
CBoolPair Write_ATime;
CBoolPair Write_MTime;
- bool _volumeMode;
+ bool _useMultiThreadMixer;
+
+ // bool _volumeMode;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
@@ -117,7 +110,7 @@ public:
INTERFACE_IArchiveGetRawProps(;)
#ifdef __7Z_SET_PROPERTIES
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
#ifndef EXTRACT_ONLY
@@ -131,28 +124,29 @@ public:
private:
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CDbEx _db;
+
#ifndef _NO_CRYPTO
bool _isEncrypted;
bool _passwordIsDefined;
+ UString _password;
#endif
#ifdef EXTRACT_ONLY
#ifdef __7Z_SET_PROPERTIES
UInt32 _numThreads;
+ bool _useMultiThreadMixer;
#endif
UInt32 _crcSize;
#else
- CRecordVector<CBind> _binds;
+ CRecordVector<CBond2> _bonds;
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
- void AddDefaultMethod();
- HRESULT SetMainMethod(CCompressionMethodMode &method,
- CObjectVector<COneMethodInfo> &methodsInfo
+ HRESULT SetMainMethod(CCompressionMethodMode &method
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index aff5809..2f6a072 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -18,11 +18,11 @@ using namespace NWindows;
namespace NArchive {
namespace N7z {
-static const wchar_t *k_LZMA_Name = L"LZMA";
-static const wchar_t *kDefaultMethodName = L"LZMA2";
-static const wchar_t *k_Copy_Name = L"Copy";
+static const char *k_LZMA_Name = "LZMA";
+static const char *kDefaultMethodName = "LZMA2";
+static const char *k_Copy_Name = "Copy";
-static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
+static const char *k_MatchFinder_ForHeaders = "BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
@@ -42,7 +42,7 @@ HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodI
{
if (!FindMethod(
EXTERNAL_CODECS_VARS
- m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
+ m.MethodName, dest.Id, dest.NumStreams))
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
@@ -54,48 +54,62 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
return S_OK;
COneMethodInfo m;
m.MethodName = k_LZMA_Name;
- m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
- m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders);
+ m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
+ m.AddProp_Level(k_Level_ForHeaders);
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
- m.AddNumThreadsProp(1);
+ m.AddProp_NumThreads(1);
- CMethodFull methodFull;
- RINOK(PropsMethod_To_FullMethod(methodFull, m));
- headerMethod.Methods.Add(methodFull);
- return S_OK;
-}
-
-void CHandler::AddDefaultMethod()
-{
- FOR_VECTOR (i, _methods)
- {
- UString &methodName = _methods[i].MethodName;
- if (methodName.IsEmpty())
- methodName = kDefaultMethodName;
- }
- if (_methods.IsEmpty())
- {
- COneMethodInfo m;
- m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
- _methods.Add(m);
- }
+ CMethodFull &methodFull = headerMethod.Methods.AddNew();
+ return PropsMethod_To_FullMethod(methodFull, m);
}
HRESULT CHandler::SetMainMethod(
- CCompressionMethodMode &methodMode,
- CObjectVector<COneMethodInfo> &methods
+ CCompressionMethodMode &methodMode
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
- AddDefaultMethod();
+ methodMode.Bonds = _bonds;
+
+ CObjectVector<COneMethodInfo> methods = _methods;
+
+ {
+ FOR_VECTOR (i, methods)
+ {
+ AString &methodName = methods[i].MethodName;
+ if (methodName.IsEmpty())
+ methodName = kDefaultMethodName;
+ }
+ if (methods.IsEmpty())
+ {
+ COneMethodInfo &m = methods.AddNew();
+ m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
+ methodMode.DefaultMethod_was_Inserted = true;
+ }
+ }
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ // if (methodMode.Bonds.IsEmpty())
+ {
+ FOR_VECTOR (k, methodMode.Bonds)
+ {
+ CBond2 &bond = methodMode.Bonds[k];
+ bond.InCoder++;
+ bond.OutCoder++;
+ }
+ methods.Insert(0, _filterMethod);
+ methodMode.Filter_was_Inserted = true;
+ }
+ }
const UInt64 kSolidBytes_Min = (1 << 24);
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
bool needSolid = false;
+
FOR_VECTOR (i, methods)
{
COneMethodInfo &oneMethodInfo = methods[i];
@@ -105,9 +119,8 @@ HRESULT CHandler::SetMainMethod(
#endif
);
- CMethodFull methodFull;
+ CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
- methodMode.Methods.Add(methodFull);
if (methodFull.Id != k_Copy)
needSolid = true;
@@ -125,6 +138,7 @@ HRESULT CHandler::SetMainMethod(
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
default: continue;
}
+
_numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
@@ -268,7 +282,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
- if (db)
+
+ if (db && !db->Files.IsEmpty())
{
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
@@ -494,14 +509,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewData)
{
- NCOM::CPropVariant prop;
- RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
- if (prop.vt != VT_UI8)
- return E_INVALIDARG;
- ui.Size = (UInt64)prop.uhVal.QuadPart;
- if (ui.Size != 0 && ui.IsAnti)
- return E_INVALIDARG;
+ ui.Size = 0;
+ if (!ui.IsDir)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ ui.Size = (UInt64)prop.uhVal.QuadPart;
+ if (ui.Size != 0 && ui.IsAnti)
+ return E_INVALIDARG;
+ }
}
+
updateItems.Add(ui);
}
@@ -517,18 +537,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CCompressionMethodMode methodMode, headerMethod;
- HRESULT res = SetMainMethod(methodMode, _methods
+ HRESULT res = SetMainMethod(methodMode
#ifndef _7ZIP_ST
, _numThreads
#endif
);
RINOK(res);
- methodMode.Binds = _binds;
RINOK(SetHeaderMethod(headerMethod));
+
#ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads;
+ methodMode.MultiThreadMixer = _useMultiThreadMixer;
headerMethod.NumThreads = 1;
+ headerMethod.MultiThreadMixer = _useMultiThreadMixer;
#endif
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
@@ -542,7 +564,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
- if (methodMode.PasswordIsDefined && (BSTR)password)
+ if (methodMode.PasswordIsDefined && password)
methodMode.Password = password;
}
@@ -550,6 +572,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool encryptHeaders = false;
+ #ifndef _NO_CRYPTO
+ if (!methodMode.PasswordIsDefined && _passwordIsDefined)
+ {
+ // if header is compressed, we use that password for updated archive
+ methodMode.PasswordIsDefined = true;
+ methodMode.Password = _password;
+ }
+ #endif
+
if (methodMode.PasswordIsDefined)
{
if (_encryptHeadersSpecified)
@@ -569,12 +600,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (numItems < 2)
compressMainHeader = false;
+ int level = GetLevel();
+
CUpdateOptions options;
options.Method = &methodMode;
- options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;
- int level = GetLevel();
- options.UseFilters = level != 0 && _autoFilter;
- options.MaxFilter = level >= 8;
+ options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
+ options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
+ options.MaxFilter = (level >= 8);
+ options.AnalysisLevel = GetAnalysisLevel();
options.HeaderOptions.CompressMainHeader = compressMainHeader;
/*
@@ -586,8 +619,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.NumSolidFiles = _numSolidFiles;
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
+ options.UseTypeSorting = _useTypeSorting;
+
options.RemoveSfxBlock = _removeSfxBlock;
- options.VolumeMode = _volumeMode;
+ // options.VolumeMode = _volumeMode;
+
+ options.MultiThreadMixer = _useMultiThreadMixer;
COutArchive archive;
CArchiveDatabaseOut newDatabase;
@@ -635,20 +672,22 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END
}
-static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
{
stream = 0;
- int index = ParseStringToUInt32(srcString, coder);
- if (index == 0)
- return E_INVALIDARG;
- srcString.Delete(0, index);
+ {
+ unsigned index = ParseStringToUInt32(srcString, coder);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.DeleteFrontal(index);
+ }
if (srcString[0] == 's')
{
srcString.Delete(0);
- int index = ParseStringToUInt32(srcString, stream);
+ unsigned index = ParseStringToUInt32(srcString, stream);
if (index == 0)
return E_INVALIDARG;
- srcString.Delete(0, index);
+ srcString.DeleteFrontal(index);
}
return S_OK;
}
@@ -667,8 +706,12 @@ void COutHandler::InitProps()
Write_ATime.Init();
Write_MTime.Init();
- _volumeMode = false;
+ _useMultiThreadMixer = true;
+
+ // _volumeMode = false;
+
InitSolid();
+ _useTypeSorting = false;
}
HRESULT COutHandler::SetSolidFromString(const UString &s)
@@ -762,7 +805,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
UInt32 number;
int index = ParseStringToUInt32(name, number);
- UString realName = name.Ptr(index);
+ // UString realName = name.Ptr(index);
if (index == 0)
{
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
@@ -787,15 +830,19 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
- if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
+ if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+
+ if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
+
+ // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
- _binds.Clear();
+ _bonds.Clear();
InitProps();
for (UInt32 i = 0; i < numProps; i++)
@@ -812,15 +859,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
name.Delete(0);
- CBind bind;
- RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));
+
+ CBond2 bond;
+ RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
if (name[0] != ':')
return E_INVALIDARG;
name.Delete(0);
- RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));
+ UInt32 inStream = 0;
+ RINOK(ParseBond(name, bond.InCoder, inStream));
+ if (inStream != 0)
+ return E_INVALIDARG;
if (!name.IsEmpty())
return E_INVALIDARG;
- _binds.Add(bind);
+ _bonds.Add(bond);
continue;
}
@@ -831,40 +882,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (numEmptyMethods > 0)
{
unsigned k;
- for (k = 0; k < _binds.Size(); k++)
+ for (k = 0; k < _bonds.Size(); k++)
{
- const CBind &bind = _binds[k];
- if (bind.InCoder < (UInt32)numEmptyMethods ||
- bind.OutCoder < (UInt32)numEmptyMethods)
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder < (UInt32)numEmptyMethods ||
+ bond.OutCoder < (UInt32)numEmptyMethods)
return E_INVALIDARG;
}
- for (k = 0; k < _binds.Size(); k++)
+ for (k = 0; k < _bonds.Size(); k++)
{
- CBind &bind = _binds[k];
- bind.InCoder -= (UInt32)numEmptyMethods;
- bind.OutCoder -= (UInt32)numEmptyMethods;
+ CBond2 &bond = _bonds[k];
+ bond.InCoder -= (UInt32)numEmptyMethods;
+ bond.OutCoder -= (UInt32)numEmptyMethods;
}
_methods.DeleteFrontal(numEmptyMethods);
}
- AddDefaultMethod();
-
- if (!_filterMethod.MethodName.IsEmpty())
- {
- FOR_VECTOR (k, _binds)
- {
- CBind &bind = _binds[k];
- bind.InCoder++;
- bind.OutCoder++;
- }
- _methods.Insert(0, _filterMethod);
- }
-
- FOR_VECTOR (k, _binds)
+ FOR_VECTOR (k, _bonds)
{
- const CBind &bind = _binds[k];
- if (bind.InCoder >= (UInt32)_methods.Size() ||
- bind.OutCoder >= (UInt32)_methods.Size())
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder >= (UInt32)_methods.Size() ||
+ bond.OutCoder >= (UInt32)_methods.Size())
return E_INVALIDARG;
}
diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
index 78b5061..7de6eee 100644
--- a/CPP/7zip/Archive/7z/7zHeader.h
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -96,6 +96,53 @@ namespace NID
};
}
+
+const UInt32 k_Copy = 0;
+const UInt32 k_Delta = 3;
+
+const UInt32 k_LZMA2 = 0x21;
+
+const UInt32 k_SWAP2 = 0x20302;
+const UInt32 k_SWAP4 = 0x20304;
+
+const UInt32 k_LZMA = 0x30101;
+const UInt32 k_PPMD = 0x30401;
+
+const UInt32 k_Deflate = 0x40108;
+const UInt32 k_BZip2 = 0x40202;
+
+const UInt32 k_BCJ = 0x3030103;
+const UInt32 k_BCJ2 = 0x303011B;
+const UInt32 k_PPC = 0x3030205;
+const UInt32 k_IA64 = 0x3030401;
+const UInt32 k_ARM = 0x3030501;
+const UInt32 k_ARMT = 0x3030701;
+const UInt32 k_SPARC = 0x3030805;
+
+const UInt32 k_AES = 0x6F10701;
+
+
+static inline bool IsFilterMethod(UInt64 m)
+{
+ if (m > (UInt64)0xFFFFFFFF)
+ return false;
+ switch ((UInt32)m)
+ {
+ case k_Delta:
+ case k_BCJ:
+ case k_BCJ2:
+ case k_PPC:
+ case k_IA64:
+ case k_ARM:
+ case k_ARMT:
+ case k_SPARC:
+ case k_SWAP2:
+ case k_SWAP4:
+ return true;
+ }
+ return false;
+}
+
}}
#endif
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index 5a85507..b03bc89 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,9 +32,6 @@ using namespace NCOM;
namespace NArchive {
namespace N7z {
-static const UInt32 k_LZMA2 = 0x21;
-static const UInt32 k_LZMA = 0x030101;
-
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{
v.ClearAndSetSize(size);
@@ -43,78 +40,6 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
-static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)
-{
- if (index >= (UInt32)v.Size())
- return true;
- bool res = v[index];
- v[index] = true;
- return res;
-}
-
-bool CFolder::CheckStructure(unsigned numUnpackSizes) const
-{
- const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it
- const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax
- const unsigned kNumBindsMax = 32;
-
- if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)
- return false;
-
- {
- CBoolVector v;
- BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());
-
- unsigned i;
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))
- return false;
- for (i = 0; i < PackStreams.Size(); i++)
- if (BoolVector_GetAndSet(v, PackStreams[i]))
- return false;
-
- BoolVector_Fill_False(v, numUnpackSizes);
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))
- return false;
- }
-
- UInt32 mask[kMaskSize];
- unsigned i;
- for (i = 0; i < kMaskSize; i++)
- mask[i] = 0;
-
- {
- CUIntVector inStreamToCoder, outStreamToCoder;
- for (i = 0; i < Coders.Size(); i++)
- {
- CNum j;
- const CCoderInfo &coder = Coders[i];
- for (j = 0; j < coder.NumInStreams; j++)
- inStreamToCoder.Add(i);
- for (j = 0; j < coder.NumOutStreams; j++)
- outStreamToCoder.Add(i);
- }
-
- for (i = 0; i < BindPairs.Size(); i++)
- {
- const CBindPair &bp = BindPairs[i];
- mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);
- }
- }
-
- for (i = 0; i < kMaskSize; i++)
- for (unsigned j = 0; j < kMaskSize; j++)
- if (((1 << j) & mask[i]) != 0)
- mask[i] |= mask[j];
-
- for (i = 0; i < kMaskSize; i++)
- if (((1 << i) & mask[i]) != 0)
- return false;
-
- return true;
-}
-
class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {};
@@ -168,6 +93,8 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *d
Byte external = archive->ReadByte();
if (external != 0)
{
+ if (!dataVector)
+ ThrowIncorrect();
CNum dataIndex = archive->ReadNum();
if (dataIndex >= dataVector->Size())
ThrowIncorrect();
@@ -193,6 +120,8 @@ Byte CInByte2::ReadByte()
void CInByte2::ReadBytes(Byte *data, size_t size)
{
+ if (size == 0)
+ return;
if (size > _size - _pos)
ThrowEndOfData();
memcpy(data, _buffer + _pos, size);
@@ -218,41 +147,48 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
processed = 0;
return 0;
}
- Byte firstByte = *p++;
+
+ unsigned b = *p++;
size--;
- if ((firstByte & 0x80) == 0)
+
+ if ((b & 0x80) == 0)
{
processed = 1;
- return firstByte;
+ return b;
}
- Byte mask = 0x40;
+
if (size == 0)
{
processed = 0;
return 0;
}
+
UInt64 value = (UInt64)*p;
p++;
size--;
+
for (unsigned i = 1; i < 8; i++)
{
- if ((firstByte & mask) == 0)
+ unsigned mask = (unsigned)0x80 >> i;
+ if ((b & mask) == 0)
{
- UInt64 highPart = firstByte & (mask - 1);
- value += (highPart << (i * 8));
+ UInt64 high = b & (mask - 1);
+ value |= (high << (i * 8));
processed = i + 1;
return value;
}
+
if (size == 0)
{
processed = 0;
return 0;
}
+
value |= ((UInt64)*p << (i * 8));
p++;
size--;
- mask >>= 1;
}
+
processed = 9;
return value;
}
@@ -344,6 +280,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
for (;;)
{
UInt32 readSize = kBufSize - kHeaderSize;
+ if (searchHeaderSizeLimit)
{
UInt64 rem = *searchHeaderSizeLimit - offset;
if (readSize > rem)
@@ -351,10 +288,12 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (readSize == 0)
return S_FALSE;
}
+
UInt32 processed = 0;
RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
if (processed == 0)
return S_FALSE;
+
for (UInt32 pos = 0;;)
{
const Byte *p = buf + pos + 1;
@@ -376,6 +315,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
}
}
+
offset += processed;
memmove(buf, buf + processed, kHeaderSize);
}
@@ -415,13 +355,15 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
void CInByte2::ParseFolder(CFolder &folder)
{
- CNum numCoders = ReadNum();
+ UInt32 numCoders = ReadNum();
+
+ if (numCoders == 0)
+ ThrowUnsupported();
folder.Coders.SetSize(numCoders);
- CNum numInStreams = 0;
- CNum numOutStreams = 0;
- CNum i;
+ UInt32 numInStreams = 0;
+ UInt32 i;
for (i = 0; i < numCoders; i++)
{
CCoderInfo &coder = folder.Coders[i];
@@ -441,14 +383,14 @@ void CInByte2::ParseFolder(CFolder &folder)
if ((mainByte & 0x10) != 0)
{
- coder.NumInStreams = ReadNum();
- coder.NumOutStreams = ReadNum();
+ coder.NumStreams = ReadNum();
+ /* numOutStreams = */ ReadNum();
}
else
{
- coder.NumInStreams = 1;
- coder.NumOutStreams = 1;
+ coder.NumStreams = 1;
}
+
if ((mainByte & 0x20) != 0)
{
CNum propsSize = ReadNum();
@@ -458,27 +400,27 @@ void CInByte2::ParseFolder(CFolder &folder)
else
coder.Props.Free();
}
- numInStreams += coder.NumInStreams;
- numOutStreams += coder.NumOutStreams;
+ numInStreams += coder.NumStreams;
}
- CNum numBindPairs = numOutStreams - 1;
- folder.BindPairs.SetSize(numBindPairs);
- for (i = 0; i < numBindPairs; i++)
+ UInt32 numBonds = numCoders - 1;
+ folder.Bonds.SetSize(numBonds);
+ for (i = 0; i < numBonds; i++)
{
- CBindPair &bp = folder.BindPairs[i];
- bp.InIndex = ReadNum();
- bp.OutIndex = ReadNum();
+ CBond &bp = folder.Bonds[i];
+ bp.PackIndex = ReadNum();
+ bp.UnpackIndex = ReadNum();
}
- if (numInStreams < numBindPairs)
+ if (numInStreams < numBonds)
ThrowUnsupported();
- CNum numPackStreams = numInStreams - numBindPairs;
+ UInt32 numPackStreams = numInStreams - numBonds;
folder.PackStreams.SetSize(numPackStreams);
+
if (numPackStreams == 1)
{
for (i = 0; i < numInStreams; i++)
- if (folder.FindBindPairForInStream(i) < 0)
+ if (folder.FindBond_for_PackStream(i) < 0)
{
folder.PackStreams[0] = i;
break;
@@ -509,12 +451,12 @@ void CDatabase::GetPath(unsigned index, UString &path) const
return;
size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset - 1;
+ size_t size = NameOffsets[index + 1] - offset;
- if (size >= (1 << 20))
+ if (size >= (1 << 28))
return;
- wchar_t *s = path.GetBuffer((unsigned)size);
+ wchar_t *s = path.GetBuf((unsigned)size - 1);
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
@@ -533,7 +475,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const
#endif
- path.ReleaseBuffer((unsigned)size);
+ path.ReleaseBuf_SetLen((unsigned)size - 1);
}
HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
@@ -592,7 +534,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
{
unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
- do
+ for (; len != 0; len--)
{
p -= 2;
--s;
@@ -601,7 +543,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
c = WCHAR_PATH_SEPARATOR;
*s = c;
}
- while (--len);
+
const CFileItem &file = Files[cur];
cur = file.Parent;
if (cur < 0)
@@ -639,6 +581,9 @@ void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
}
}
+#define k_Scan_NumCoders_MAX 64
+#define k_Scan_NumCodersStreams_in_Folder_MAX 64
+
void CInArchive::ReadPackInfo(CFolders &f)
{
CNum numPackStreams = ReadNum();
@@ -692,27 +637,31 @@ void CInArchive::ReadUnpackInfo(
folders.FoCodersDataOffset.Alloc(numFolders + 1);
folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
- CRecordVector<bool> InStreamUsed;
- CRecordVector<bool> OutStreamUsed;
+ CBoolVector StreamUsed;
+ CBoolVector CoderUsed;
CNum packStreamIndex = 0;
CNum fo;
CInByte2 *inByte = _inByteBack;
+
for (fo = 0; fo < numFolders; fo++)
{
- UInt32 numOutStreams = 0;
UInt32 indexOfMainStream = 0;
UInt32 numPackStreams = 0;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
- numOutStreams = 0;
CNum numInStreams = 0;
CNum numCoders = inByte->ReadNum();
+
+ if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
+ ThrowUnsupported();
+
for (CNum ci = 0; ci < numCoders; ci++)
{
Byte mainByte = inByte->ReadByte();
if ((mainByte & 0xC0) != 0)
ThrowUnsupported();
+
unsigned idSize = (mainByte & 0xF);
if (idSize > 8)
ThrowUnsupported();
@@ -725,19 +674,21 @@ void CInArchive::ReadUnpackInfo(
inByte->SkipDataNoCheck(idSize);
if (folders.ParsedMethods.IDs.Size() < 128)
folders.ParsedMethods.IDs.AddToUniqueSorted(id);
+
CNum coderInStreams = 1;
- CNum coderOutStreams = 1;
if ((mainByte & 0x10) != 0)
{
coderInStreams = inByte->ReadNum();
- coderOutStreams = inByte->ReadNum();
+ if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
+ ThrowUnsupported();
+ if (inByte->ReadNum() != 1)
+ ThrowUnsupported();
}
+
numInStreams += coderInStreams;
- if (numInStreams < coderInStreams)
- ThrowUnsupported();
- numOutStreams += coderOutStreams;
- if (numOutStreams < coderOutStreams)
+ if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
ThrowUnsupported();
+
if ((mainByte & 0x20) != 0)
{
CNum propsSize = inByte->ReadNum();
@@ -759,7 +710,7 @@ void CInArchive::ReadUnpackInfo(
}
}
- if (numOutStreams == 1 && numInStreams == 1)
+ if (numCoders == 1 && numInStreams == 1)
{
indexOfMainStream = 0;
numPackStreams = 1;
@@ -767,60 +718,64 @@ void CInArchive::ReadUnpackInfo(
else
{
UInt32 i;
- if (numOutStreams == 0)
- ThrowUnsupported();
- CNum numBindPairs = numOutStreams - 1;
- if (numInStreams < numBindPairs)
+ CNum numBonds = numCoders - 1;
+ if (numInStreams < numBonds)
ThrowUnsupported();
- if (numInStreams >= 256 || numOutStreams >= 256)
- ThrowUnsupported();
-
- InStreamUsed.ClearAndSetSize(numInStreams);
- for (i = 0; i < numInStreams; i++)
- InStreamUsed[i] = false;
- OutStreamUsed.ClearAndSetSize(numOutStreams);
- for (i = 0; i < numOutStreams; i++)
- OutStreamUsed[i] = false;
+ BoolVector_Fill_False(StreamUsed, numInStreams);
+ BoolVector_Fill_False(CoderUsed, numCoders);
- for (i = 0; i < numBindPairs; i++)
+ for (i = 0; i < numBonds; i++)
{
CNum index = ReadNum();
- if (index >= numInStreams || InStreamUsed[index])
+ if (index >= numInStreams || StreamUsed[index])
ThrowUnsupported();
- InStreamUsed[index] = true;
+ StreamUsed[index] = true;
+
index = ReadNum();
- if (index >= numOutStreams || OutStreamUsed[index])
+ if (index >= numCoders || CoderUsed[index])
ThrowUnsupported();
- OutStreamUsed[index] = true;
+ CoderUsed[index] = true;
}
- numPackStreams = numInStreams - numBindPairs;
+ numPackStreams = numInStreams - numBonds;
if (numPackStreams != 1)
for (i = 0; i < numPackStreams; i++)
- inByte->ReadNum(); // PackStreams
+ {
+ CNum index = inByte->ReadNum(); // PackStreams
+ if (index >= numInStreams || StreamUsed[index])
+ ThrowUnsupported();
+ StreamUsed[index] = true;
+ }
- for (i = 0; i < numOutStreams; i++)
- if (!OutStreamUsed[i])
+ for (i = 0; i < numCoders; i++)
+ if (!CoderUsed[i])
{
indexOfMainStream = i;
break;
}
- if (i == numOutStreams)
+
+ if (i == numCoders)
ThrowUnsupported();
}
+
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
- numCodersOutStreams += numOutStreams;
+ numCodersOutStreams += numCoders;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
+ if (numPackStreams > folders.NumPackStreams - packStreamIndex)
+ ThrowIncorrect();
packStreamIndex += numPackStreams;
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
}
+
size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
folders.CodersData.CopyFrom(startBufPtr, dataSize);
+
+ // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
}
WaitId(NID::kCodersUnpackSize);
@@ -1105,13 +1060,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
unpackSizes,
digests);
- CDecoder decoder(
- #ifdef _ST_MODE
- false
- #else
- true
- #endif
- );
+ CDecoder decoder(_useMixerMT);
for (CNum i = 0; i < folders.NumFolders; i++)
{
@@ -1127,14 +1076,20 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
outStreamSpec->Init(data, unpackSize);
HRESULT result = decoder.Decode(
- EXTERNAL_CODECS_LOC_VARS
- _stream, baseOffset + dataOffset,
- folders, i,
- outStream, NULL
- _7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , false, 1
- #endif
+ EXTERNAL_CODECS_LOC_VARS
+ _stream, baseOffset + dataOffset,
+ folders, i,
+ NULL, // *unpackSize
+
+ outStream,
+ NULL, // *compressProgress
+ NULL // **inStreamMainRes
+
+ _7Z_DECODER_CRYPRO_VARS
+ #if !defined(_7ZIP_ST) && !defined(_SFX)
+ , false // mtMode
+ , 1 // numThreads
+ #endif
);
RINOK(result);
@@ -1142,7 +1097,10 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
ThrowIncorrect();
}
- HeadersSize += folders.PackPositions[folders.NumPackStreams];
+
+ if (folders.PackPositions)
+ HeadersSize += folders.PackPositions[folders.NumPackStreams];
+
return S_OK;
}
@@ -1195,9 +1153,8 @@ HRESULT CInArchive::ReadHeader(
if (type == NID::kFilesInfo)
{
- CNum numFiles = ReadNum();
+ const CNum numFiles = ReadNum();
db.Files.ClearAndSetSize(numFiles);
- CNum i;
/*
db.Files.Reserve(numFiles);
CNum i;
@@ -1208,7 +1165,7 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
- if (numFiles > 0 && !digests.Defs.IsEmpty())
+ if (numFiles > 0 && !digests.Defs.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector;
@@ -1219,8 +1176,8 @@ HRESULT CInArchive::ReadHeader(
for (;;)
{
- UInt64 type = ReadID();
- if (type == NID::kEnd)
+ const UInt64 type2 = ReadID();
+ if (type2 == NID::kEnd)
break;
UInt64 size = ReadNumber();
if (size > _inByteBack->GetRem())
@@ -1229,9 +1186,9 @@ HRESULT CInArchive::ReadHeader(
switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);
bool addPropIdToList = true;
bool isKnownType = true;
- if (type > ((UInt32)1 << 30))
+ if (type2 > ((UInt32)1 << 30))
isKnownType = false;
- else switch((UInt32)type)
+ else switch ((UInt32)type2)
{
case NID::kName:
{
@@ -1265,7 +1222,7 @@ HRESULT CInArchive::ReadHeader(
ReadBoolVector2(db.Files.Size(), boolVector);
CStreamSwitch streamSwitch;
streamSwitch.Set(this, &dataVector);
- for (i = 0; i < numFiles; i++)
+ for (CNum i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
file.AttribDefined = boolVector[i];
@@ -1308,7 +1265,7 @@ HRESULT CInArchive::ReadHeader(
{
ReadBoolVector(numFiles, emptyStreamVector);
numEmptyStreams = 0;
- for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)
+ for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++)
if (emptyStreamVector[i])
numEmptyStreams++;
@@ -1382,28 +1339,34 @@ HRESULT CInArchive::ReadHeader(
if (isKnownType)
{
if (addPropIdToList)
- db.ArcInfo.FileInfoPopIDs.Add(type);
+ db.ArcInfo.FileInfoPopIDs.Add(type2);
}
else
{
db.UnsupportedFeatureWarning = true;
_inByteBack->SkipRem();
}
- // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02)
+ // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)
if (_inByteBack->GetRem() != 0)
ThrowIncorrect();
}
type = ReadID(); // Read (NID::kEnd) end of headers
+ if (numFiles - numEmptyStreams != unpackSizes.Size())
+ ThrowUnsupported();
+
CNum emptyFileIndex = 0;
CNum sizeIndex = 0;
CNum numAntiItems = 0;
+
+ CNum i;
+
for (i = 0; i < numEmptyStreams; i++)
if (antiFileVector[i])
numAntiItems++;
-
+
for (i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
@@ -1444,13 +1407,13 @@ HRESULT CInArchive::ReadHeader(
void CDbEx::FillLinks()
{
- FolderStartFileIndex.ClearAndSetSize(NumFolders);
-
- FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());
+ FolderStartFileIndex.Alloc(NumFolders);
+ FileIndexToFolderIndexMap.Alloc(Files.Size());
CNum folderIndex = 0;
CNum indexInFolder = 0;
unsigned i;
+
for (i = 0; i < Files.Size(); i++)
{
bool emptyStream = !Files[i].HasStream;
@@ -1489,6 +1452,7 @@ void CDbEx::FillLinks()
if (indexInFolder != 0)
ThrowIncorrect();
*/
+
for (;;)
{
if (folderIndex >= NumFolders)
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index d78eca2..260d8f7 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -26,8 +26,8 @@ namespace N7z {
#define _7Z_DECODER_CRYPRO_VARS_DECL
#define _7Z_DECODER_CRYPRO_VARS
#else
-#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined
-#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined
+#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
+#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
#endif
struct CParsedMethods
@@ -39,6 +39,11 @@ struct CParsedMethods
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
};
+struct CFolderEx: public CFolder
+{
+ unsigned UnpackCoder;
+};
+
struct CFolders
{
CNum NumPackStreams;
@@ -47,10 +52,10 @@ struct CFolders
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
- CUInt32DefVector FolderCRCs; // NumFolders
+ CUInt32DefVector FolderCRCs; // NumFolders
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
- CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
@@ -61,10 +66,15 @@ struct CFolders
CParsedMethods ParsedMethods;
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
+ void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
+ {
+ ParseFolderInfo(folderIndex, folder);
+ folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
+ }
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
{
- return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];
+ return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
}
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
@@ -77,6 +87,8 @@ struct CFolders
return PackPositions[index + 1] - PackPositions[index];
}
+ CFolders(): NumPackStreams(0), NumFolders(0) {}
+
void Clear()
{
NumPackStreams = 0;
@@ -103,9 +115,9 @@ struct CDatabase: public CFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
- CRecordVector<bool> IsAnti;
+ CBoolVector IsAnti;
/*
- CRecordVector<bool> IsAux;
+ CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureIDs;
*/
@@ -148,13 +160,14 @@ struct CDatabase: public CFolders
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
- const void * GetName(unsigned index) const
+ /*
+ const void* GetName(unsigned index) const
{
if (!NameOffsets || !NamesBuf)
return NULL;
- return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
+ return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
};
-
+ */
void GetPath(unsigned index, UString &path) const;
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
};
@@ -181,8 +194,9 @@ struct CInArchiveInfo
struct CDbEx: public CDatabase
{
CInArchiveInfo ArcInfo;
- CRecordVector<CNum> FolderStartFileIndex;
- CRecordVector<CNum> FileIndexToFolderIndexMap;
+
+ CObjArray<CNum> FolderStartFileIndex;
+ CObjArray<CNum> FileIndexToFolderIndexMap;
UInt64 HeadersSize;
UInt64 PhySize;
@@ -234,8 +248,8 @@ struct CDbEx: public CDatabase
// SecureOffsets.Clear();
ArcInfo.Clear();
- FolderStartFileIndex.Clear();
- FileIndexToFolderIndexMap.Clear();
+ FolderStartFileIndex.Free();
+ FileIndexToFolderIndexMap.Free();
HeadersSize = 0;
PhySize = 0;
@@ -243,22 +257,22 @@ struct CDbEx: public CDatabase
void FillLinks();
- UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const
+ UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
{
return ArcInfo.DataStartPosition +
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
}
- UInt64 GetFolderFullPackSize(unsigned folderIndex) const
+ UInt64 GetFolderFullPackSize(CNum folderIndex) const
{
return
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex[folderIndex]];
}
- UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const
+ UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
{
- unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;
+ size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
return PackPositions[i + 1] - PackPositions[i];
}
@@ -327,6 +341,8 @@ class CInArchive
UInt64 HeadersSize;
+ bool _useMixerMT;
+
void AddByteStream(const Byte *buffer, size_t size);
void DeleteByteStream(bool needUpdatePos)
@@ -340,7 +356,6 @@ class CInArchive
}
}
-private:
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
@@ -396,7 +411,11 @@ private:
_7Z_DECODER_CRYPRO_VARS_DECL
);
public:
- CInArchive(): _numInByteBufs(0) { }
+ CInArchive(bool useMixerMT):
+ _numInByteBufs(0),
+ _useMixerMT(useMixerMT)
+ {}
+
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close();
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index 90e6869..935ee43 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -13,8 +13,6 @@
namespace NArchive {
namespace N7z {
-const UInt64 k_AES = 0x06F10701;
-
typedef UInt32 CNum;
const CNum kNumMax = 0x7FFFFFFF;
const CNum kNumNoIndex = 0xFFFFFFFF;
@@ -23,71 +21,70 @@ struct CCoderInfo
{
CMethodId MethodID;
CByteBuffer Props;
- CNum NumInStreams;
- CNum NumOutStreams;
+ UInt32 NumStreams;
- bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+ bool IsSimpleCoder() const { return NumStreams == 1; }
};
-struct CBindPair
+struct CBond
{
- CNum InIndex;
- CNum OutIndex;
+ UInt32 PackIndex;
+ UInt32 UnpackIndex;
};
struct CFolder
{
+ CLASS_NO_COPY(CFolder)
+public:
CObjArray2<CCoderInfo> Coders;
- CObjArray2<CBindPair> BindPairs;
- CObjArray2<CNum> PackStreams;
+ CObjArray2<CBond> Bonds;
+ CObjArray2<UInt32> PackStreams;
- CNum GetNumOutStreams() const
- {
- CNum result = 0;
- FOR_VECTOR(i, Coders)
- result += Coders[i].NumOutStreams;
- return result;
- }
+ CFolder() {}
- int FindBindPairForInStream(CNum inStreamIndex) const
+ bool IsDecodingSupported() const { return Coders.Size() <= 32; }
+
+ int Find_in_PackStreams(UInt32 packStream) const
{
- FOR_VECTOR(i, BindPairs)
- if (BindPairs[i].InIndex == inStreamIndex)
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == packStream)
return i;
return -1;
}
- int FindBindPairForOutStream(CNum outStreamIndex) const
+
+ int FindBond_for_PackStream(UInt32 packStream) const
{
- FOR_VECTOR(i, BindPairs)
- if (BindPairs[i].OutIndex == outStreamIndex)
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
return i;
return -1;
}
- int FindPackStreamArrayIndex(CNum inStreamIndex) const
+
+ /*
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
- FOR_VECTOR(i, PackStreams)
- if (PackStreams[i] == inStreamIndex)
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
return i;
return -1;
}
- int GetIndexOfMainOutStream() const
+ int FindOutCoder() const
{
- for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)
- if (FindBindPairForOutStream(i) < 0)
+ for (int i = (int)Coders.Size() - 1; i >= 0; i--)
+ if (FindBond_for_UnpackStream(i) < 0)
return i;
- throw 1;
+ return -1;
}
+ */
bool IsEncrypted() const
{
- for (int i = Coders.Size() - 1; i >= 0; i--)
+ FOR_VECTOR(i, Coders)
if (Coders[i].MethodID == k_AES)
return true;
return false;
}
-
- bool CheckStructure(unsigned numUnpackSizes) const;
};
struct CUInt32DefVector
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index cf776ce..0989978 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -199,7 +199,7 @@ void COutArchive::WriteNumber(UInt64 value)
mask >>= 1;
}
WriteByte(firstByte);
- for (;i > 0; i--)
+ for (; i > 0; i--)
{
WriteByte((Byte)value);
value >>= 8;
@@ -254,31 +254,33 @@ void COutArchive::WriteFolder(const CFolder &folder)
{
WriteNumber(folder.Coders.Size());
unsigned i;
+
for (i = 0; i < folder.Coders.Size(); i++)
{
const CCoderInfo &coder = folder.Coders[i];
{
- size_t propsSize = coder.Props.Size();
-
UInt64 id = coder.MethodID;
- int idSize;
+ unsigned idSize;
for (idSize = 1; idSize < sizeof(id); idSize++)
if ((id >> (8 * idSize)) == 0)
break;
- Byte longID[15];
- for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
- longID[t] = (Byte)(id & 0xFF);
- Byte b;
- b = (Byte)(idSize & 0xF);
+ idSize &= 0xF;
+ Byte temp[16];
+ for (unsigned t = idSize; t != 0; t--, id >>= 8)
+ temp[t] = (Byte)(id & 0xFF);
+
+ Byte b = (Byte)(idSize);
bool isComplex = !coder.IsSimpleCoder();
b |= (isComplex ? 0x10 : 0);
- b |= ((propsSize != 0) ? 0x20 : 0 );
- WriteByte(b);
- WriteBytes(longID, idSize);
+
+ size_t propsSize = coder.Props.Size();
+ b |= ((propsSize != 0) ? 0x20 : 0);
+ temp[0] = b;
+ WriteBytes(temp, idSize + 1);
if (isComplex)
{
- WriteNumber(coder.NumInStreams);
- WriteNumber(coder.NumOutStreams);
+ WriteNumber(coder.NumStreams);
+ WriteNumber(1); // NumOutStreams;
}
if (propsSize == 0)
continue;
@@ -286,17 +288,17 @@ void COutArchive::WriteFolder(const CFolder &folder)
WriteBytes(coder.Props, propsSize);
}
}
- for (i = 0; i < folder.BindPairs.Size(); i++)
+
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- const CBindPair &bindPair = folder.BindPairs[i];
- WriteNumber(bindPair.InIndex);
- WriteNumber(bindPair.OutIndex);
+ const CBond &bond = folder.Bonds[i];
+ WriteNumber(bond.PackIndex);
+ WriteNumber(bond.UnpackIndex);
}
+
if (folder.PackStreams.Size() > 1)
for (i = 0; i < folder.PackStreams.Size(); i++)
- {
WriteNumber(folder.PackStreams[i]);
- }
}
void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
@@ -521,7 +523,10 @@ HRESULT COutArchive::EncodeStream(
UInt64 unpackSize;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
+ stream,
+ // NULL,
+ &dataSize64,
+ folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
return S_OK;
}
@@ -535,13 +540,13 @@ void COutArchive::WriteHeader(
*/
_useAlign = true;
- unsigned i;
-
- UInt64 packedSize = 0;
- for (i = 0; i < db.PackSizes.Size(); i++)
- packedSize += db.PackSizes[i];
+ {
+ UInt64 packSize = 0;
+ FOR_VECTOR (i, db.PackSizes)
+ packSize += db.PackSizes[i];
+ headerOffset = packSize;
+ }
- headerOffset = packedSize;
WriteByte(NID::kHeader);
@@ -555,7 +560,7 @@ void COutArchive::WriteHeader(
CRecordVector<UInt64> unpackSizes;
CUInt32DefVector digests;
- for (i = 0; i < db.Files.Size(); i++)
+ FOR_VECTOR (i, db.Files)
{
const CFileItem &file = db.Files[i];
if (!file.HasStream)
@@ -583,14 +588,17 @@ void COutArchive::WriteHeader(
CBoolVector emptyStreamVector;
emptyStreamVector.ClearAndSetSize(db.Files.Size());
unsigned numEmptyStreams = 0;
- for (i = 0; i < db.Files.Size(); i++)
- if (db.Files[i].HasStream)
- emptyStreamVector[i] = false;
- else
- {
- emptyStreamVector[i] = true;
- numEmptyStreams++;
- }
+ {
+ FOR_VECTOR (i, db.Files)
+ if (db.Files[i].HasStream)
+ emptyStreamVector[i] = false;
+ else
+ {
+ emptyStreamVector[i] = true;
+ numEmptyStreams++;
+ }
+ }
+
if (numEmptyStreams != 0)
{
WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
@@ -600,7 +608,8 @@ void COutArchive::WriteHeader(
antiVector.ClearAndSetSize(numEmptyStreams);
bool thereAreEmptyFiles = false, thereAreAntiItems = false;
unsigned cur = 0;
- for (i = 0; i < db.Files.Size(); i++)
+
+ FOR_VECTOR (i, db.Files)
{
const CFileItem &file = db.Files[i];
if (file.HasStream)
@@ -667,17 +676,21 @@ void COutArchive::WriteHeader(
CBoolVector boolVector;
boolVector.ClearAndSetSize(db.Files.Size());
unsigned numDefined = 0;
- for (i = 0; i < db.Files.Size(); i++)
+
{
- bool defined = db.Files[i].AttribDefined;
- boolVector[i] = defined;
- if (defined)
- numDefined++;
+ FOR_VECTOR (i, db.Files)
+ {
+ bool defined = db.Files[i].AttribDefined;
+ boolVector[i] = defined;
+ if (defined)
+ numDefined++;
+ }
}
+
if (numDefined != 0)
{
WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);
- for (i = 0; i < db.Files.Size(); i++)
+ FOR_VECTOR (i, db.Files)
{
const CFileItem &file = db.Files[i];
if (file.AttribDefined)
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index 07dbd63..86034f3 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -29,6 +29,8 @@ public:
}
void WriteBytes(const void *data, size_t size)
{
+ if (size == 0)
+ return;
if (size > _size - _pos)
throw 1;
memcpy(_data + _pos, data, size);
@@ -92,7 +94,7 @@ struct COutFolders
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
CRecordVector<CNum> NumUnpackStreamsVector;
- CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
void OutFoldersClear()
{
diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
index 345c61b..388ac76 100644
--- a/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -13,8 +13,8 @@ namespace N7z {
struct CPropMap
{
- UInt64 FilePropID;
- STATPROPSTG StatPROPSTG;
+ UInt32 FilePropID;
+ CStatProp StatProp;
};
static const CPropMap kPropMap[] =
@@ -24,18 +24,18 @@ static const CPropMap kPropMap[] =
{ NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
#ifdef _MULTI_PACK
- { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } },
- { 101, { L"Pack1", kpidPackedSize1, VT_UI8 } },
- { 102, { L"Pack2", kpidPackedSize2, VT_UI8 } },
- { 103, { L"Pack3", kpidPackedSize3, VT_UI8 } },
- { 104, { L"Pack4", kpidPackedSize4, VT_UI8 } },
+ { 100, { "Pack0", kpidPackedSize0, VT_UI8 } },
+ { 101, { "Pack1", kpidPackedSize1, VT_UI8 } },
+ { 102, { "Pack2", kpidPackedSize2, VT_UI8 } },
+ { 103, { "Pack3", kpidPackedSize3, VT_UI8 } },
+ { 104, { "Pack4", kpidPackedSize4, VT_UI8 } },
#endif
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
- { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
+ { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
@@ -44,20 +44,12 @@ static const CPropMap kPropMap[] =
#ifndef _SFX
,
- { 97, { NULL,kpidEncrypted, VT_BOOL } },
- { 98, { NULL,kpidMethod, VT_BSTR } },
- { 99, { NULL,kpidBlock, VT_UI4 } }
+ { 97, { NULL, kpidEncrypted, VT_BOOL } },
+ { 98, { NULL, kpidMethod, VT_BSTR } },
+ { 99, { NULL, kpidBlock, VT_UI4 } }
#endif
};
-static int FindPropInMap(UInt64 filePropID)
-{
- for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)
- if (kPropMap[i].FilePropID == filePropID)
- return i;
- return -1;
-}
-
static void CopyOneItem(CRecordVector<UInt64> &src,
CRecordVector<UInt64> &dest, UInt32 item)
{
@@ -98,7 +90,7 @@ void CHandler::FillPopIDs()
_fileInfoPopIDs.Clear();
#ifdef _7Z_VOL
- if(_volumes.Size() < 1)
+ if (_volumes.Size() < 1)
return;
const CVolume &volume = _volumes.Front();
const CArchiveDatabaseEx &_db = volume.Database;
@@ -131,6 +123,7 @@ void CHandler::FillPopIDs()
_fileInfoPopIDs.Add(98);
_fileInfoPopIDs.Add(99);
#endif
+
#ifdef _MULTI_PACK
_fileInfoPopIDs.Add(100);
_fileInfoPopIDs.Add(101);
@@ -155,16 +148,27 @@ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
- if ((int)index >= _fileInfoPopIDs.Size())
+ if (index >= _fileInfoPopIDs.Size())
return E_INVALIDARG;
- int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
- if (indexInMap == -1)
- return E_INVALIDARG;
- const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
- *propID = srcItem.propid;
- *varType = srcItem.vt;
- *name = 0;
- return S_OK;
+ UInt64 id = _fileInfoPopIDs[index];
+ for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
+ {
+ const CPropMap &pr = kPropMap[i];
+ if (pr.FilePropID == id)
+ {
+ const CStatProp &st = pr.StatProp;
+ *propID = st.PropID;
+ *varType = st.vt;
+ /*
+ if (st.lpwstrName)
+ *name = ::SysAllocString(st.lpwstrName);
+ else
+ */
+ *name = NULL;
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
}
}}
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
index ae4e890..3e8cfb6 100644
--- a/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -9,17 +9,13 @@
namespace NArchive {
namespace N7z {
-IMP_CreateArcIn
-IMP_CreateArcOut
+static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
-static CArcInfo g_ArcInfo =
- { "7z", "7z", 0, 7,
- 6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},
+REGISTER_ARC_IO_DECREMENT_SIG(
+ "7z", "7z", NULL, 7,
+ k_Signature_Dec,
0,
NArcInfoFlags::kFindSignature,
- REF_CreateArc_Pair };
-
-REGISTER_ARC_DEC_SIG(7z)
-// REGISTER_ARC(7z)
+ NULL);
}}
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
index 0058ac2..0994128 100644
--- a/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -3,10 +3,10 @@
#ifndef __7Z_SPEC_STREAM_H
#define __7Z_SPEC_STREAM_H
-#include "../../IStream.h"
-#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
class CSequentialInStreamSizeCount2:
public ISequentialInStream,
public ICompressGetSubStreamSize,
@@ -18,14 +18,14 @@ class CSequentialInStreamSizeCount2:
public:
void Init(ISequentialInStream *stream)
{
+ _size = 0;
+ _getSubStreamSize.Release();
_stream = stream;
- _getSubStreamSize = 0;
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
- _size = 0;
}
UInt64 GetSize() const { return _size; }
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 87f3e0d..509a330 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -13,7 +13,6 @@
#include "../../Compress/CopyCoder.h"
#include "../Common/ItemNameUtils.h"
-#include "../Common/OutStreamWithCRC.h"
#include "7zDecode.h"
#include "7zEncode.h"
@@ -25,9 +24,396 @@
namespace NArchive {
namespace N7z {
-#ifdef MY_CPU_X86_OR_AMD64
-#define USE_86_FILTER
-#endif
+
+#define k_X86 k_BCJ
+
+struct CFilterMode
+{
+ UInt32 Id;
+ UInt32 Delta;
+
+ CFilterMode(): Id(0), Delta(0) {}
+
+ void SetDelta()
+ {
+ if (Id == k_IA64)
+ Delta = 16;
+ else if (Id == k_ARM || Id == k_PPC || Id == k_SPARC)
+ Delta = 4;
+ else if (Id == k_ARMT)
+ Delta = 2;
+ else
+ Delta = 0;
+ }
+};
+
+
+/* ---------- PE ---------- */
+
+#define MZ_SIG 0x5A4D
+
+#define PE_SIG 0x00004550
+#define PE_OptHeader_Magic_32 0x10B
+#define PE_OptHeader_Magic_64 0x20B
+#define PE_SectHeaderSize 40
+#define PE_SECT_EXECUTE 0x20000000
+
+static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ if (size < 512 || GetUi16(buf) != MZ_SIG)
+ return 0;
+
+ const Byte *p;
+ UInt32 peOffset, optHeaderSize, filterId;
+
+ peOffset = GetUi32(buf + 0x3C);
+ if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)
+ return 0;
+ p = buf + peOffset;
+ if (GetUi32(p) != PE_SIG)
+ return 0;
+ p += 4;
+
+ switch (GetUi16(p))
+ {
+ case 0x014C:
+ case 0x8664: filterId = k_X86; break;
+
+ /*
+ IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE
+ IMAGE_FILE_MACHINE_THUMB 0x01C2 // ARM Thumb / Thumb-2 LE
+ IMAGE_FILE_MACHINE_ARMNT 0x01C4 // ARM Thumb-2, LE
+ Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2).
+ */
+
+ case 0x01C0: // WinCE old
+ case 0x01C2: filterId = k_ARM; break; // WinCE new
+ case 0x01C4: filterId = k_ARMT; break; // WinRT
+
+ case 0x0200: filterId = k_IA64; break;
+ default: return 0;
+ }
+
+ optHeaderSize = GetUi16(p + 16);
+ if (optHeaderSize > (1 << 10))
+ return 0;
+
+ p += 20; /* headerSize */
+
+ switch (GetUi16(p))
+ {
+ case PE_OptHeader_Magic_32:
+ case PE_OptHeader_Magic_64:
+ break;
+ default:
+ return 0;
+ }
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+/* ---------- ELF ---------- */
+
+#define ELF_SIG 0x464C457F
+
+#define ELF_CLASS_32 1
+#define ELF_CLASS_64 2
+
+#define ELF_DATA_2LSB 1
+#define ELF_DATA_2MSB 2
+
+static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
+static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); }
+// static UInt64 Get64(const Byte *p, Bool be) { if (be) return GetBe64(p); return GetUi64(p); }
+
+static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ Bool /* is32, */ be;
+ UInt32 filterId;
+
+ if (size < 512 || buf[6] != 1) /* ver */
+ return 0;
+
+ if (GetUi32(buf) != ELF_SIG)
+ return 0;
+
+ switch (buf[4])
+ {
+ case ELF_CLASS_32: /* is32 = True; */ break;
+ case ELF_CLASS_64: /* is32 = False; */ break;
+ default: return 0;
+ }
+
+ switch (buf[5])
+ {
+ case ELF_DATA_2LSB: be = False; break;
+ case ELF_DATA_2MSB: be = True; break;
+ default: return 0;
+ }
+
+ switch (Get16(buf + 0x12, be))
+ {
+ case 3:
+ case 6:
+ case 62: filterId = k_X86; break;
+ case 2:
+ case 18:
+ case 43: filterId = k_SPARC; break;
+ case 20:
+ case 21: if (!be) return 0; filterId = k_PPC; break;
+ case 40: if ( be) return 0; filterId = k_ARM; break;
+
+ /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes.
+ So we don't use IA-64 filter for IA-64 ELF */
+ // case 50: if ( be) return 0; filterId = k_IA64; break;
+
+ default: return 0;
+ }
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+
+/* ---------- Mach-O ---------- */
+
+#define MACH_SIG_BE_32 0xCEFAEDFE
+#define MACH_SIG_BE_64 0xCFFAEDFE
+#define MACH_SIG_LE_32 0xFEEDFACE
+#define MACH_SIG_LE_64 0xFEEDFACF
+
+#define MACH_ARCH_ABI64 (1 << 24)
+#define MACH_MACHINE_386 7
+#define MACH_MACHINE_ARM 12
+#define MACH_MACHINE_SPARC 14
+#define MACH_MACHINE_PPC 18
+#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)
+#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)
+
+static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ UInt32 filterId, numCommands, commandsSize;
+
+ if (size < 512)
+ return 0;
+
+ Bool /* mode64, */ be;
+ switch (GetUi32(buf))
+ {
+ case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;
+ case MACH_SIG_BE_64: /* mode64 = True; */ be = True; break;
+ case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break;
+ case MACH_SIG_LE_64: /* mode64 = True; */ be = False; break;
+ default: return 0;
+ }
+
+ switch (Get32(buf + 4, be))
+ {
+ case MACH_MACHINE_386:
+ case MACH_MACHINE_AMD64: filterId = k_X86; break;
+ case MACH_MACHINE_ARM: if ( be) return 0; filterId = k_ARM; break;
+ case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break;
+ case MACH_MACHINE_PPC:
+ case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break;
+ default: return 0;
+ }
+
+ numCommands = Get32(buf + 0x10, be);
+ commandsSize = Get32(buf + 0x14, be);
+
+ if (commandsSize > (1 << 24) || numCommands > (1 << 18))
+ return 0;
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+/* ---------- WAV ---------- */
+
+#define WAV_SUBCHUNK_fmt 0x20746D66
+#define WAV_SUBCHUNK_data 0x61746164
+
+#define RIFF_SIG 0x46464952
+
+static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ UInt32 subChunkSize, pos;
+ if (size < 0x2C)
+ return False;
+
+ if (GetUi32(buf + 0) != RIFF_SIG ||
+ GetUi32(buf + 8) != 0x45564157 || // WAVE
+ GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt)
+ return False;
+ subChunkSize = GetUi32(buf + 0x10);
+ /* [0x14 = format] = 1 (PCM) */
+ if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)
+ return False;
+
+ unsigned numChannels = GetUi16(buf + 0x16);
+ unsigned bitsPerSample = GetUi16(buf + 0x22);
+
+ if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256)
+ return False;
+
+ pos = 0x14 + subChunkSize;
+
+ const int kNumSubChunksTests = 10;
+ // Do we need to scan more than 3 sub-chunks?
+ for (int i = 0; i < kNumSubChunksTests; i++)
+ {
+ if (pos + 8 > size)
+ return False;
+ subChunkSize = GetUi32(buf + pos + 4);
+ if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)
+ {
+ unsigned delta = numChannels * (bitsPerSample >> 3);
+ if (delta >= 256)
+ return False;
+ filterMode->Id = k_Delta;
+ filterMode->Delta = delta;
+ return True;
+ }
+ if (subChunkSize > (1 << 16))
+ return False;
+ pos += subChunkSize + 8;
+ }
+ return False;
+}
+
+static Bool ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ filterMode->Id = 0;
+ filterMode->Delta = 0;
+
+ if (Parse_EXE(buf, size, filterMode)) return True;
+ if (Parse_ELF(buf, size, filterMode)) return True;
+ if (Parse_MACH(buf, size, filterMode)) return True;
+ return Parse_WAV(buf, size, filterMode);
+}
+
+
+
+
+struct CFilterMode2: public CFilterMode
+{
+ bool Encrypted;
+ unsigned GroupIndex;
+
+ CFilterMode2(): Encrypted(false) {}
+
+ int Compare(const CFilterMode2 &m) const
+ {
+ if (!Encrypted)
+ {
+ if (m.Encrypted)
+ return -1;
+ }
+ else if (!m.Encrypted)
+ return 1;
+
+ if (Id < m.Id) return -1;
+ if (Id > m.Id) return 1;
+
+ if (Delta < m.Delta) return -1;
+ if (Delta > m.Delta) return 1;
+
+ return 0;
+ }
+
+ bool operator ==(const CFilterMode2 &m) const
+ {
+ return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted;
+ }
+};
+
+static unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m)
+{
+ unsigned i;
+ for (i = 0; i < filters.Size(); i++)
+ {
+ const CFilterMode2 &m2 = filters[i];
+ if (m == m2)
+ return i;
+ /*
+ if (m.Encrypted != m2.Encrypted)
+ {
+ if (!m.Encrypted)
+ break;
+ continue;
+ }
+
+ if (m.Id < m2.Id) break;
+ if (m.Id != m2.Id) continue;
+
+ if (m.Delta < m2.Delta) break;
+ if (m.Delta != m2.Delta) continue;
+ */
+ }
+ // filters.Insert(i, m);
+ // return i;
+ return filters.Add(m);
+}
+
+static inline bool Is86Filter(CMethodId m)
+{
+ return (m == k_BCJ || m == k_BCJ2);
+}
+
+static inline bool IsExeFilter(CMethodId m)
+{
+ switch (m)
+ {
+ case k_BCJ:
+ case k_BCJ2:
+ case k_ARM:
+ case k_ARMT:
+ case k_PPC:
+ case k_SPARC:
+ case k_IA64:
+ return true;
+ }
+ return false;
+}
+
+static unsigned Get_FilterGroup_for_Folder(
+ CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter)
+{
+ CFilterMode2 m;
+ m.Id = 0;
+ m.Delta = 0;
+ m.Encrypted = f.IsEncrypted();
+
+ if (extractFilter)
+ {
+ const CCoderInfo &coder = f.Coders[f.UnpackCoder];
+
+ if (coder.MethodID == k_Delta)
+ {
+ if (coder.Props.Size() == 1)
+ {
+ m.Delta = (unsigned)coder.Props[0] + 1;
+ m.Id = k_Delta;
+ }
+ }
+ else if (IsExeFilter(coder.MethodID))
+ {
+ m.Id = (UInt32)coder.MethodID;
+ if (m.Id == k_BCJ2)
+ m.Id = k_BCJ;
+ m.SetDelta();
+ }
+ }
+
+ return GetGroup(filters, m);
+}
+
+
+
static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
UInt64 position, UInt64 size, ICompressProgressInfo *progress)
@@ -44,21 +430,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
}
-static int GetReverseSlashPos(const UString &name)
-{
- int slashPos = name.ReverseFind(L'/');
- #ifdef _WIN32
- int slash1Pos = name.ReverseFind(L'\\');
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
- return slashPos;
-}
-
-int CUpdateItem::GetExtensionPos() const
+/*
+unsigned CUpdateItem::GetExtensionPos() const
{
- int slashPos = GetReverseSlashPos(Name);
- int dotPos = Name.ReverseFind(L'.');
- if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+ int slashPos = Name.ReverseFind_PathSepar();
+ int dotPos = Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
return Name.Len();
return dotPos + 1;
}
@@ -67,6 +444,7 @@ UString CUpdateItem::GetExtension() const
{
return Name.Ptr(GetExtensionPos());
}
+*/
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -91,7 +469,7 @@ static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
return CompareBuffers(c1.Props, c2.Props);
}
-static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
+static int CompareBonds(const CBond &b1, const CBond &b2)
{
RINOZ_COMP(b1.InIndex, b2.InIndex);
return MyCompare(b1.OutIndex, b2.OutIndex);
@@ -105,11 +483,11 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2)
int i;
for (i = 0; i < s1; i++)
RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
- s1 = f1.BindPairs.Size();
- s2 = f2.BindPairs.Size();
+ s1 = f1.Bonds.Size();
+ s2 = f2.Bonds.Size();
RINOZ_COMP(s1, s2);
for (i = 0; i < s1; i++)
- RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
+ RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));
return 0;
}
*/
@@ -123,36 +501,34 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
struct CFolderRepack
{
- int FolderIndex;
- int Group;
+ unsigned FolderIndex;
CNum NumCopyFiles;
};
-static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */)
+/*
+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)
{
- RINOZ_COMP(p1->Group, p2->Group);
int i1 = p1->FolderIndex;
int i2 = p2->FolderIndex;
- /*
// In that version we don't want to parse folders here, so we don't compare folders
// probably it must be improved in future
- const CDbEx &db = *(const CDbEx *)param;
- RINOZ(CompareFolders(
- db.Folders[i1],
- db.Folders[i2]));
- */
+ // const CDbEx &db = *(const CDbEx *)param;
+ // RINOZ(CompareFolders(
+ // db.Folders[i1],
+ // db.Folders[i2]));
+
return MyCompare(i1, i2);
- /*
- RINOZ_COMP(
- db.NumUnpackStreamsVector[i1],
- db.NumUnpackStreamsVector[i2]);
- if (db.NumUnpackStreamsVector[i1] == 0)
- return 0;
- return CompareFiles(
- db.Files[db.FolderStartFileIndex[i1]],
- db.Files[db.FolderStartFileIndex[i2]]);
- */
+
+ // RINOZ_COMP(
+ // db.NumUnpackStreamsVector[i1],
+ // db.NumUnpackStreamsVector[i2]);
+ // if (db.NumUnpackStreamsVector[i1] == 0)
+ // return 0;
+ // return CompareFiles(
+ // db.Files[db.FolderStartFileIndex[i1]],
+ // db.Files[db.FolderStartFileIndex[i2]]);
}
+*/
/*
we sort empty files and dirs in such order:
@@ -162,7 +538,7 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2
- Dir.Anti (reverse name sorted)
*/
-static int CompareEmptyItems(const int *p1, const int *p2, void *param)
+static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)
{
const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
const CUpdateItem &u1 = updateItems[*p1];
@@ -182,11 +558,11 @@ static int CompareEmptyItems(const int *p1, const int *p2, void *param)
}
static const char *g_Exts =
- " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"
+ " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
" zip jar ear war msi"
" 3gp avi mov mpeg mpg mpe wmv"
" aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
- " swf "
+ " swf"
" chm hxi hxs"
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
" awg ps eps cgm dxf svg vrml wmf emf ai md"
@@ -195,25 +571,28 @@ static const char *g_Exts =
" iso bin nrg mdf img pdi tar cpio xpi"
" vfd vhd vud vmc vsv"
" vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
- " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"
+ " inl inc idl acf asa"
+ " h hpp hxx c cpp cxx m mm go swift"
+ " rc java cs rs pas bas vb cls ctl frm dlg def"
" f77 f f90 f95"
- " asm sql manifest dep "
- " mak clw csproj vcproj sln dsp dsw "
- " class "
- " bat cmd"
+ " asm s"
+ " sql manifest dep"
+ " mak clw csproj vcproj sln dsp dsw"
+ " class"
+ " bat cmd bash sh"
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
- " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
+ " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs"
" text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
" sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
" abw afp cwk lwp wpd wps wpt wrf wri"
" abf afm bdf fon mgf otf pcf pfa snf ttf"
" dbf mdb nsf ntf wdb db fdb gdb"
- " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
+ " exe dll ocx vbx sfx sys tlb awx com obj lib out o so"
" pdb pch idb ncb opt";
-static int GetExtIndex(const char *ext)
+static unsigned GetExtIndex(const char *ext)
{
- int extIndex = 1;
+ unsigned extIndex = 1;
const char *p = g_Exts;
for (;;)
{
@@ -222,7 +601,7 @@ static int GetExtIndex(const char *ext)
return extIndex;
if (c == ' ')
continue;
- int pos = 0;
+ unsigned pos = 0;
for (;;)
{
char c2 = ext[pos++];
@@ -248,8 +627,8 @@ struct CRefItem
{
const CUpdateItem *UpdateItem;
UInt32 Index;
- UInt32 ExtensionPos;
- UInt32 NamePos;
+ unsigned ExtensionPos;
+ unsigned NamePos;
unsigned ExtensionIndex;
CRefItem() {};
@@ -262,10 +641,10 @@ struct CRefItem
{
if (sortByType)
{
- int slashPos = GetReverseSlashPos(ui.Name);
+ int slashPos = ui.Name.ReverseFind_PathSepar();
NamePos = slashPos + 1;
- int dotPos = ui.Name.ReverseFind(L'.');
- if (dotPos < 0 || dotPos < slashPos)
+ int dotPos = ui.Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
ExtensionPos = ui.Name.Len();
else
{
@@ -396,35 +775,193 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para
struct CSolidGroup
{
CRecordVector<UInt32> Indices;
+
+ CRecordVector<CFolderRepack> folderRefs;
};
-static const wchar_t *g_ExeExts[] =
+static const char * const g_ExeExts[] =
{
- L"dll"
- , L"exe"
- , L"ocx"
- , L"sfx"
- , L"sys"
+ "dll"
+ , "exe"
+ , "ocx"
+ , "sfx"
+ , "sys"
};
static bool IsExeExt(const wchar_t *ext)
{
- for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
- if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0)
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
+ if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i]))
return true;
return false;
}
+struct CAnalysis
+{
+ CMyComPtr<IArchiveUpdateCallbackFile> Callback;
+ CByteBuffer Buffer;
+
+ bool ParseWav;
+ bool ParseExe;
+ bool ParseAll;
+
+ CAnalysis():
+ ParseWav(true),
+ ParseExe(false),
+ ParseAll(false)
+ {}
+
+ HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode);
+};
-static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)
+static const size_t kAnalysisBufSize = 1 << 14;
+
+HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode)
+{
+ filterMode.Id = 0;
+ filterMode.Delta = 0;
+
+ CFilterMode filterModeTemp = filterMode;
+
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ int dotPos = ui.Name.ReverseFind_Dot();
+
+ // if (dotPos > slashPos)
+ {
+ bool needReadFile = ParseAll;
+
+ bool probablyIsSameIsa = false;
+
+ if (!needReadFile || !Callback)
+ {
+ const wchar_t *ext;
+ if (dotPos > slashPos)
+ ext = ui.Name.Ptr(dotPos + 1);
+ else
+ ext = ui.Name.RightPtr(0);
+
+ // p7zip uses the trick to store posix attributes in high 16 bits
+ if (ui.Attrib & 0x8000)
+ {
+ unsigned st_mode = ui.Attrib >> 16;
+ // st_mode = 00111;
+ if ((st_mode & 00111) && (ui.Size >= 2048))
+ {
+ #ifndef _WIN32
+ probablyIsSameIsa = true;
+ #endif
+ needReadFile = true;
+ }
+ }
+
+ if (IsExeExt(ext))
+ {
+ needReadFile = true;
+ #ifdef _WIN32
+ probablyIsSameIsa = true;
+ needReadFile = ParseExe;
+ #endif
+ }
+ else if (StringsAreEqualNoCase_Ascii(ext, "wav"))
+ {
+ needReadFile = ParseWav;
+ }
+ /*
+ else if (!needReadFile && ParseUnixExt)
+ {
+ if (StringsAreEqualNoCase_Ascii(ext, "so")
+ || StringsAreEqualNoCase_Ascii(ext, ""))
+
+ needReadFile = true;
+ }
+ */
+ }
+
+ if (needReadFile && Callback)
+ {
+ if (Buffer.Size() != kAnalysisBufSize)
+ {
+ Buffer.Alloc(kAnalysisBufSize);
+ }
+ {
+ CMyComPtr<ISequentialInStream> stream;
+ HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze);
+ if (result == S_OK && stream)
+ {
+ size_t size = kAnalysisBufSize;
+ result = ReadStream(stream, Buffer, &size);
+ stream.Release();
+ // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));
+ if (result == S_OK)
+ {
+ Bool parseRes = ParseFile(Buffer, size, &filterModeTemp);
+ if (parseRes && filterModeTemp.Delta == 0)
+ {
+ filterModeTemp.SetDelta();
+ if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta)
+ {
+ if (ui.Size % filterModeTemp.Delta != 0)
+ {
+ parseRes = false;
+ }
+ }
+ }
+ if (!parseRes)
+ {
+ filterModeTemp.Id = 0;
+ filterModeTemp.Delta = 0;
+ }
+ }
+ }
+ }
+ }
+ else if ((needReadFile && !Callback) || probablyIsSameIsa)
+ {
+ #ifdef MY_CPU_X86_OR_AMD64
+ if (probablyIsSameIsa)
+ filterModeTemp.Id = k_X86;
+ #endif
+ }
+ }
+
+ filterMode = filterModeTemp;
+ return S_OK;
+}
+
+static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m)
{
m.Id = methodID;
- m.NumInStreams = numInStreams;
- m.NumOutStreams = 1;
+ m.NumStreams = numStreams;
+}
+
+static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
+{
+ for (unsigned c = 1; c < mode.Methods.Size(); c++)
+ {
+ if (!mode.IsThereBond_to_Coder(c))
+ {
+ CBond2 bond;
+ bond.OutCoder = 0;
+ bond.OutStream = 0;
+ bond.InCoder = c;
+ mode.Bonds.Add(bond);
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
}
-static void AddBcj2Methods(CCompressionMethodMode &mode)
+static HRESULT AddFilterBond(CCompressionMethodMode &mode)
{
+ if (!mode.Bonds.IsEmpty())
+ return AddBondForFilter(mode);
+ return S_OK;
+}
+
+static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
+{
+ // mode.Methods[0] must be k_BCJ2 method !
+
CMethodFull m;
GetMethodFull(k_LZMA, 1, m);
@@ -433,54 +970,121 @@ static void AddBcj2Methods(CCompressionMethodMode &mode)
m.AddProp32(NCoderPropID::kNumThreads, 1);
m.AddProp32(NCoderPropID::kLitPosBits, 2);
m.AddProp32(NCoderPropID::kLitContextBits, 0);
- // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");
+ // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
+
+ unsigned methodIndex = mode.Methods.Size();
+
+ if (mode.Bonds.IsEmpty())
+ {
+ for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++)
+ {
+ CBond2 bond;
+ bond.OutCoder = i;
+ bond.OutStream = 0;
+ bond.InCoder = i + 1;
+ mode.Bonds.Add(bond);
+ }
+ }
mode.Methods.Add(m);
mode.Methods.Add(m);
- CBind bind;
- bind.OutCoder = 0;
- bind.InStream = 0;
- bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind);
- bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind);
- bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind);
+ RINOK(AddBondForFilter(mode));
+ CBond2 bond;
+ bond.OutCoder = 0;
+ bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond);
+ bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond);
+ return S_OK;
}
-static void MakeExeMethod(CCompressionMethodMode &mode,
- bool useFilters, bool addFilter, bool bcj2Filter)
+static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
+ const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter)
{
- if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)
- return;
- if (mode.Methods.Size() == 2)
+ if (mode.Filter_was_Inserted)
{
- if (mode.Methods[0].Id == k_BCJ2)
- AddBcj2Methods(mode);
- return;
+ const CMethodFull &m = mode.Methods[0];
+ CMethodId id = m.Id;
+ if (id == k_BCJ2)
+ return AddBcj2Methods(mode);
+ if (!m.IsSimpleCoder())
+ return E_NOTIMPL;
+ // if (Bonds.IsEmpty()) we can create bonds later
+ return AddFilterBond(mode);
}
- if (!addFilter)
- return;
- bcj2Filter = bcj2Filter;
- #ifdef USE_86_FILTER
- if (bcj2Filter)
+
+ if (filterMode.Id == 0)
+ return S_OK;
+
+ CMethodFull &m = mode.Methods.InsertNew(0);
+
+ {
+ FOR_VECTOR(k, mode.Bonds)
+ {
+ CBond2 &bond = mode.Bonds[k];
+ bond.InCoder++;
+ bond.OutCoder++;
+ }
+ }
+
+ HRESULT res;
+
+ if (bcj2Filter && Is86Filter(filterMode.Id))
{
- CMethodFull m;
GetMethodFull(k_BCJ2, 4, m);
- mode.Methods.Insert(0, m);
- AddBcj2Methods(mode);
+ res = AddBcj2Methods(mode);
}
else
{
- CMethodFull m;
- GetMethodFull(k_BCJ, 1, m);
- mode.Methods.Insert(0, m);
- CBind bind;
- bind.OutCoder = 0;
- bind.InStream = 0;
- bind.InCoder = 1;
- bind.OutStream = 0;
- mode.Binds.Add(bind);
+ GetMethodFull(filterMode.Id, 1, m);
+ if (filterMode.Id == k_Delta)
+ m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
+ res = AddFilterBond(mode);
+
+ int alignBits = -1;
+ if (filterMode.Id == k_Delta || filterMode.Delta != 0)
+ {
+ if (filterMode.Delta == 1) alignBits = 0;
+ else if (filterMode.Delta == 2) alignBits = 1;
+ else if (filterMode.Delta == 4) alignBits = 2;
+ else if (filterMode.Delta == 8) alignBits = 3;
+ else if (filterMode.Delta == 16) alignBits = 4;
+ }
+ else
+ {
+ // alignBits = GetAlignForFilterMethod(filterMode.Id);
+ }
+
+ if (res == S_OK && alignBits >= 0)
+ {
+ unsigned nextCoder = 1;
+ if (!mode.Bonds.IsEmpty())
+ {
+ nextCoder = mode.Bonds.Back().InCoder;
+ }
+ if (nextCoder < mode.Methods.Size())
+ {
+ CMethodFull &nextMethod = mode.Methods[nextCoder];
+ if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
+ {
+ if (!nextMethod.Are_Lzma_Model_Props_Defined())
+ {
+ if (alignBits != 0)
+ {
+ if (alignBits > 2 || filterMode.Id == k_Delta)
+ nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits);
+ unsigned lc = 0;
+ if (alignBits < 3)
+ lc = 3 - alignBits;
+ nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
+ nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits);
+ }
+ }
+ }
+ }
+ }
}
- #endif
+
+ return res;
}
@@ -503,133 +1107,336 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
// file.IsAltStream = ui.IsAltStream;
}
-class CFolderOutStream2:
- public ISequentialOutStream,
+class CRepackInStreamWithSizes:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
public CMyUnknownImp
{
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
- const CDbEx *_db;
+ CMyComPtr<ISequentialInStream> _stream;
+ // UInt64 _size;
const CBoolVector *_extractStatuses;
- CMyComPtr<ISequentialOutStream> _outStream;
UInt32 _startIndex;
- unsigned _currentIndex;
+public:
+ const CDbEx *_db;
+
+ void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses)
+ {
+ _startIndex = startIndex;
+ _extractStatuses = extractStatuses;
+ // _size = 0;
+ _stream = stream;
+ }
+ // UInt64 GetSize() const { return _size; }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+};
+
+STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ return _stream->Read(data, size, processedSize);
+ /*
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return result;
+ */
+}
+
+STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ if (subStream >= _extractStatuses->Size())
+ return S_FALSE; // E_FAIL;
+ unsigned index = (unsigned)subStream;
+ if ((*_extractStatuses)[index])
+ {
+ const CFileItem &fi = _db->Files[_startIndex + index];
+ if (fi.HasStream)
+ *value = fi.Size;
+ }
+ return S_OK;
+}
+
+
+class CRepackStreamBase
+{
+protected:
+ bool _needWrite;
bool _fileIsOpen;
+ bool _calcCrc;
+ UInt32 _crc;
UInt64 _rem;
- void OpenFile();
- void CloseFile();
- HRESULT CloseFileAndSetResult();
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+ unsigned _currentIndex;
+
+ HRESULT OpenFile();
+ HRESULT CloseFile();
HRESULT ProcessEmptyFiles();
+
public:
- MY_UNKNOWN_IMP
-
- CFolderOutStream2()
- {
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
- }
+ const CDbEx *_db;
+ CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;
+ CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback;
- HRESULT Init(const CDbEx *db, UInt32 startIndex,
- const CBoolVector *extractStatuses, ISequentialOutStream *outStream);
- void ReleaseOutStream();
+ HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);
HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
-HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex,
- const CBoolVector *extractStatuses, ISequentialOutStream *outStream)
+HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)
{
- _db = db;
_startIndex = startIndex;
_extractStatuses = extractStatuses;
- _outStream = outStream;
_currentIndex = 0;
_fileIsOpen = false;
+
return ProcessEmptyFiles();
}
-void CFolderOutStream2::ReleaseOutStream()
+HRESULT CRepackStreamBase::OpenFile()
{
- _outStream.Release();
- _crcStreamSpec->ReleaseStream();
-}
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
+
+ _needWrite = (*_extractStatuses)[_currentIndex];
+ if (_opCallback)
+ {
+ RINOK(_opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, arcIndex,
+ _needWrite ?
+ NUpdateNotifyOp::kRepack :
+ NUpdateNotifyOp::kSkip));
+ }
+
+ _crc = CRC_INIT_VAL;
+ _calcCrc = (fi.CrcDefined && !fi.IsDir);
-void CFolderOutStream2::OpenFile()
-{
- _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);
- _crcStreamSpec->Init(true);
_fileIsOpen = true;
- _rem = _db->Files[_startIndex + _currentIndex].Size;
+ _rem = fi.Size;
+ return S_OK;
}
-void CFolderOutStream2::CloseFile()
+const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;
+
+HRESULT CRepackStreamBase::CloseFile()
{
- _crcStreamSpec->ReleaseStream();
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
_fileIsOpen = false;
_currentIndex++;
-}
+ if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))
+ return S_OK;
-HRESULT CFolderOutStream2::CloseFileAndSetResult()
-{
- const CFileItem &file = _db->Files[_startIndex + _currentIndex];
- CloseFile();
- return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;
+ if (_extractCallback)
+ {
+ RINOK(_extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, arcIndex,
+ NExtract::NOperationResult::kCRCError));
+ }
+ // return S_FALSE;
+ return k_My_HRESULT_CRC_ERROR;
}
-HRESULT CFolderOutStream2::ProcessEmptyFiles()
+HRESULT CRepackStreamBase::ProcessEmptyFiles()
{
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
{
- OpenFile();
- RINOK(CloseFileAndSetResult());
+ RINOK(OpenFile());
+ RINOK(CloseFile());
}
return S_OK;
}
+
+
+
+#ifndef _7ZIP_ST
+
+class CFolderOutStream2:
+ public CRepackStreamBase,
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<ISequentialOutStream> _stream;
+
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
+
while (size != 0)
{
if (_fileIsOpen)
{
- UInt32 cur = size < _rem ? size : (UInt32)_rem;
- RINOK(_crcStream->Write(data, cur, &cur));
- if (cur == 0)
- break;
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ HRESULT result = S_OK;
+ if (_needWrite)
+ result = _stream->Write(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ if (processedSize)
+ *processedSize += cur;
data = (const Byte *)data + cur;
size -= cur;
_rem -= cur;
- if (processedSize != NULL)
- *processedSize += cur;
if (_rem == 0)
{
- RINOK(CloseFileAndSetResult());
+ RINOK(CloseFile());
RINOK(ProcessEmptyFiles());
- continue;
}
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
}
- else
+
+ RINOK(ProcessEmptyFiles());
+ if (_currentIndex == _extractStatuses->Size())
+ {
+ // we don't support write cut here
+ return E_FAIL;
+ }
+ RINOK(OpenFile());
+ }
+
+ return S_OK;
+}
+
+#endif
+
+
+
+static const UInt32 kTempBufSize = 1 << 16;
+
+class CFolderInStream2:
+ public CRepackStreamBase,
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ Byte *_buf;
+public:
+ CMyComPtr<ISequentialInStream> _inStream;
+ HRESULT Result;
+
+ MY_UNKNOWN_IMP
+
+ CFolderInStream2():
+ Result(S_OK)
+ {
+ _buf = new Byte[kTempBufSize];
+ }
+
+ ~CFolderInStream2()
+ {
+ delete []_buf;
+ }
+
+ void Init() { Result = S_OK; }
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
{
- RINOK(ProcessEmptyFiles());
- if (_currentIndex == _extractStatuses->Size())
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+
+ void *buf;
+ if (_needWrite)
+ buf = data;
+ else
{
- // we don't support partial extracting
- return E_FAIL;
+ buf = _buf;
+ if (cur > kTempBufSize)
+ cur = kTempBufSize;
+ }
+
+ HRESULT result = _inStream->Read(buf, cur, &cur);
+ _crc = CrcUpdate(_crc, buf, cur);
+ _rem -= cur;
+
+ if (_needWrite)
+ {
+ data = (Byte *)data + cur;
+ size -= cur;
+ if (processedSize)
+ *processedSize += cur;
+ }
+
+ if (result != S_OK)
+ Result = result;
+
+ if (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
}
- OpenFile();
+
+ RINOK(result);
+
+ if (cur == 0)
+ return E_FAIL;
+
+ continue;
+ }
+
+ RINOK(ProcessEmptyFiles());
+ if (_currentIndex == _extractStatuses->Size())
+ {
+ return S_OK;
}
+ RINOK(OpenFile());
}
+
return S_OK;
}
-class CThreadDecoder: public CVirtThread
+
+class CThreadDecoder
+ #ifndef _7ZIP_ST
+ : public CVirtThread
+ #endif
{
public:
+ CDecoder Decoder;
+
+ CThreadDecoder(bool multiThreadMixer):
+ Decoder(multiThreadMixer)
+ {
+ #ifndef _7ZIP_ST
+ if (multiThreadMixer)
+ {
+ MtMode = false;
+ NumThreads = 1;
+ FosSpec = new CFolderOutStream2;
+ Fos = FosSpec;
+ Result = E_FAIL;
+ }
+ #endif
+ // UnpackSize = 0;
+ // send_UnpackSize = false;
+ }
+
+ #ifndef _7ZIP_ST
+
HRESULT Result;
CMyComPtr<IInStream> InStream;
@@ -639,33 +1446,30 @@ public:
UInt64 StartPos;
const CFolders *Folders;
int FolderIndex;
+
+ // bool send_UnpackSize;
+ // UInt64 UnpackSize;
+
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
#endif
DECL_EXTERNAL_CODECS_LOC_VARS2;
- CDecoder Decoder;
#ifndef _7ZIP_ST
bool MtMode;
UInt32 NumThreads;
#endif
- CThreadDecoder():
- Decoder(true)
- {
- #ifndef _7ZIP_ST
- MtMode = false;
- NumThreads = 1;
- #endif
- FosSpec = new CFolderOutStream2;
- Fos = FosSpec;
- Result = E_FAIL;
- }
+
~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }
virtual void Execute();
+
+ #endif
};
+#ifndef _7ZIP_ST
+
void CThreadDecoder::Execute()
{
try
@@ -673,6 +1477,7 @@ void CThreadDecoder::Execute()
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
+ UString password;
#endif
Result = Decoder.Decode(
@@ -680,8 +1485,14 @@ void CThreadDecoder::Execute()
InStream,
StartPos,
*Folders, FolderIndex,
+
+ // send_UnpackSize ? &UnpackSize : NULL,
+ NULL, // unpackSize : FULL unpack
+
Fos,
- NULL
+ NULL, // compressProgress
+ NULL // *inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
, MtMode, NumThreads
@@ -692,21 +1503,15 @@ void CThreadDecoder::Execute()
{
Result = E_FAIL;
}
+
+ /*
if (Result == S_OK)
Result = FosSpec->CheckFinishedState();
- FosSpec->ReleaseOutStream();
+ */
+ FosSpec->_stream.Release();
}
-bool static Is86FilteredFolder(const CFolder &f)
-{
- FOR_VECTOR(i, f.Coders)
- {
- CMethodId m = f.Coders[i].MethodID;
- if (m == k_BCJ || m == k_BCJ2)
- return true;
- }
- return false;
-}
+#endif
#ifndef _NO_CRYPTO
@@ -728,14 +1533,8 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
#endif
-static const int kNumGroupsMax = 4;
-static bool Is86Group(int group) { return (group & 1) != 0; }
-static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
-static int GetGroupIndex(bool encrypted, int bcjFiltered)
- { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
-
-static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2)
+static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)
{
file = inDb.Files[index];
file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);
@@ -767,6 +1566,12 @@ HRESULT Update(
if (numSolidFiles == 0)
numSolidFiles = 1;
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
+ CMyComPtr<IArchiveExtractCallbackMessage> extractCallback;
+ updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback);
+
// size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();
/*
@@ -776,21 +1581,39 @@ HRESULT Update(
return E_NOTIMPL;
*/
- UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0;
+ UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0;
if (startBlockSize > 0 && !options.RemoveSfxBlock)
{
RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
}
CIntArr fileIndexToUpdateIndexMap;
- CRecordVector<CFolderRepack> folderRefs;
UInt64 complexity = 0;
UInt64 inSizeForReduce2 = 0;
bool needEncryptedRepack = false;
- if (db != 0)
+
+ CRecordVector<CFilterMode2> filters;
+ CObjectVector<CSolidGroup> groups;
+ bool thereAreRepacks = false;
+
+ bool useFilters = options.UseFilters;
+ if (useFilters)
+ {
+ const CCompressionMethodMode &method = *options.Method;
+
+ FOR_VECTOR (i, method.Methods)
+ if (IsFilterMethod(method.Methods[i].Id))
+ {
+ useFilters = false;
+ break;
+ }
+ }
+
+ if (db)
{
fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
unsigned i;
+
for (i = 0; i < db->Files.Size(); i++)
fileIndexToUpdateIndexMap[i] = -1;
@@ -798,15 +1621,16 @@ HRESULT Update(
{
int index = updateItems[i].IndexInArchive;
if (index != -1)
- fileIndexToUpdateIndexMap[index] = i;
+ fileIndexToUpdateIndexMap[(unsigned)index] = i;
}
- for (i = 0; i < (int)db->NumFolders; i++)
+ for (i = 0; i < db->NumFolders; i++)
{
CNum indexInFolder = 0;
CNum numCopyItems = 0;
CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
UInt64 repackSize = 0;
+
for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)
{
const CFileItem &file = db->Files[fi];
@@ -828,41 +1652,51 @@ HRESULT Update(
CFolderRepack rep;
rep.FolderIndex = i;
rep.NumCopyFiles = numCopyItems;
- CFolder f;
- db->ParseFolderInfo(i, f);
- bool isEncrypted = f.IsEncrypted();
- rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));
- folderRefs.Add(rep);
- if (numCopyItems == numUnpackStreams)
+ CFolderEx f;
+ db->ParseFolderEx(i, f);
+
+ const bool isEncrypted = f.IsEncrypted();
+ const bool needCopy = (numCopyItems == numUnpackStreams);
+ const bool extractFilter = (useFilters || needCopy);
+
+ unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);
+
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+
+ groups[groupIndex].folderRefs.Add(rep);
+
+ if (needCopy)
complexity += db->GetFolderFullPackSize(i);
else
{
+ thereAreRepacks = true;
complexity += repackSize;
- if (repackSize > inSizeForReduce2)
+ if (inSizeForReduce2 < repackSize)
inSizeForReduce2 = repackSize;
if (isEncrypted)
needEncryptedRepack = true;
}
}
- folderRefs.Sort(CompareFolderRepacks, (void *)db);
}
UInt64 inSizeForReduce = 0;
- unsigned i;
- for (i = 0; i < updateItems.Size(); i++)
{
- const CUpdateItem &ui = updateItems[i];
- if (ui.NewData)
+ FOR_VECTOR (i, updateItems)
{
- complexity += ui.Size;
- if (numSolidFiles != 1)
- inSizeForReduce += ui.Size;
- else if (ui.Size > inSizeForReduce)
- inSizeForReduce = ui.Size;
+ const CUpdateItem &ui = updateItems[i];
+ if (ui.NewData)
+ {
+ complexity += ui.Size;
+ if (numSolidFiles != 1)
+ inSizeForReduce += ui.Size;
+ else if (inSizeForReduce < ui.Size)
+ inSizeForReduce = ui.Size;
+ }
}
}
- if (inSizeForReduce2 > inSizeForReduce)
+ if (inSizeForReduce < inSizeForReduce2)
inSizeForReduce = inSizeForReduce2;
RINOK(updateCallback->SetTotal(complexity));
@@ -871,52 +1705,88 @@ HRESULT Update(
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
+ #ifndef _7ZIP_ST
+
CStreamBinder sb;
- RINOK(sb.CreateEvents());
+ if (options.MultiThreadMixer)
+ {
+ RINOK(sb.CreateEvents());
+ }
+
+ #endif
- CThreadDecoder threadDecoder;
- if (!folderRefs.IsEmpty())
+ CThreadDecoder threadDecoder(options.MultiThreadMixer);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer && thereAreRepacks)
{
#ifdef EXTERNAL_CODECS
threadDecoder.__externalCodecs = __externalCodecs;
#endif
RINOK(threadDecoder.Create());
}
-
- CObjectVector<CSolidGroup> groups;
- for (i = 0; i < kNumGroupsMax; i++)
- groups.AddNew();
+ #endif
{
+ CAnalysis analysis;
+ if (options.AnalysisLevel == 0)
+ {
+ analysis.ParseWav = false;
+ analysis.ParseExe = false;
+ analysis.ParseAll = false;
+ }
+ else
+ {
+ analysis.Callback = opCallback;
+ if (options.AnalysisLevel > 0)
+ {
+ analysis.ParseWav = true;
+ if (options.AnalysisLevel >= 7)
+ {
+ analysis.ParseExe = true;
+ if (options.AnalysisLevel >= 9)
+ analysis.ParseAll = true;
+ }
+ }
+ }
+
// ---------- Split files to groups ----------
- bool useFilters = options.UseFilters;
const CCompressionMethodMode &method = *options.Method;
- if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
- useFilters = false;
- for (i = 0; i < updateItems.Size(); i++)
+
+ FOR_VECTOR (i, updateItems)
{
const CUpdateItem &ui = updateItems[i];
if (!ui.NewData || !ui.HasStream())
continue;
- bool filteredGroup = false;
+
+ CFilterMode2 fm;
if (useFilters)
{
- int dotPos = ui.Name.ReverseFind(L'.');
- if (dotPos >= 0)
- filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1));
+ RINOK(analysis.GetFilterGroup(i, ui, fm));
}
- groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);
+ fm.Encrypted = method.PasswordIsDefined;
+
+ unsigned groupIndex = GetGroup(filters, fm);
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+ groups[groupIndex].Indices.Add(i);
}
}
+
#ifndef _NO_CRYPTO
CCryptoGetTextPassword *getPasswordSpec = NULL;
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (needEncryptedRepack)
{
getPasswordSpec = new CCryptoGetTextPassword;
+ getTextPassword = getPasswordSpec;
+
+ #ifndef _7ZIP_ST
threadDecoder.getTextPassword = getPasswordSpec;
+ #endif
if (options.Method->PasswordIsDefined)
getPasswordSpec->Password = options.Method->Password;
@@ -926,7 +1796,7 @@ HRESULT Update(
return E_NOTIMPL;
CMyComBSTR password;
RINOK(getDecoderPassword->CryptoGetTextPassword(&password));
- if ((BSTR)password)
+ if (password)
getPasswordSpec->Password = password;
}
}
@@ -986,7 +1856,10 @@ HRESULT Update(
{
/* ---------- Write non-AUX dirs and Empty files ---------- */
- CRecordVector<int> emptyRefs;
+ CUIntVector emptyRefs;
+
+ unsigned i;
+
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
@@ -1003,7 +1876,9 @@ HRESULT Update(
*/
emptyRefs.Add(i);
}
+
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
+
for (i = 0; i < emptyRefs.Size(); i++)
{
const CUpdateItem &ui = updateItems[emptyRefs[i]];
@@ -1030,17 +1905,36 @@ HRESULT Update(
}
}
- unsigned folderRefIndex = 0;
lps->ProgressOffset = 0;
- for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)
{
- const CSolidGroup &group = groups[groupIndex];
+ // ---------- Sort Filters ----------
+
+ FOR_VECTOR (i, filters)
+ {
+ filters[i].GroupIndex = i;
+ }
+ filters.Sort2();
+ }
+
+ for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++)
+ {
+ const CFilterMode2 &filterMode = filters[groupIndex];
CCompressionMethodMode method = *options.Method;
- MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);
+ {
+ HRESULT res = MakeExeMethod(method, filterMode,
+ #ifdef _7ZIP_ST
+ false
+ #else
+ options.MaxFilter && options.MultiThreadMixer
+ #endif
+ );
+
+ RINOK(res);
+ }
- if (IsEncryptedGroup(groupIndex))
+ if (filterMode.Encrypted)
{
if (!method.PasswordIsDefined)
{
@@ -1059,83 +1953,266 @@ HRESULT Update(
CEncoder encoder(method);
- for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)
+ // ---------- Repack and copy old solid blocks ----------
+
+ const CSolidGroup &group = groups[filterMode.GroupIndex];
+
+ FOR_VECTOR(folderRefIndex, group.folderRefs)
{
- const CFolderRepack &rep = folderRefs[folderRefIndex];
- if (rep.Group != groupIndex)
- break;
- int folderIndex = rep.FolderIndex;
+ const CFolderRepack &rep = group.folderRefs[folderRefIndex];
+
+ unsigned folderIndex = rep.FolderIndex;
- if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])
+ CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
+
+ if (rep.NumCopyFiles == numUnpackStreams)
{
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NUpdateNotifyOp::kReplicate));
+
+ // ---------- Copy old solid block ----------
+ {
+ CNum indexInFolder = 0;
+ for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
+ {
+ if (db->Files[fi].HasStream)
+ {
+ indexInFolder++;
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)fi,
+ NUpdateNotifyOp::kReplicate));
+ }
+ }
+ }
+ }
+
UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
RINOK(WriteRange(inStream, archive.SeqStream,
- db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
+ db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
lps->ProgressOffset += packSize;
CFolder &folder = newDatabase.Folders.AddNew();
db->ParseFolderInfo(folderIndex, folder);
CNum startIndex = db->FoStartPackStreamIndex[folderIndex];
- for (unsigned j = 0; j < folder.PackStreams.Size(); j++)
+ FOR_VECTOR(j, folder.PackStreams)
{
newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));
// newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
}
- UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex];
- UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
+ size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
+ size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
for (; indexStart < indexEnd; indexStart++)
newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]);
}
else
{
+ // ---------- Repack old solid block ----------
+
CBoolVector extractStatuses;
- CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
CNum indexInFolder = 0;
-
+
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NUpdateNotifyOp::kRepack))
+ }
+
+ /* We could reduce data size of decoded folder, if we don't need to repack
+ last files in folder. But the gain in speed is small in most cases.
+ So we unpack full folder. */
+
+ UInt64 sizeToEncode = 0;
+
+ /*
+ UInt64 importantUnpackSize = 0;
+ unsigned numImportantFiles = 0;
+ UInt64 decodeSize = 0;
+ */
+
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
bool needExtract = false;
- if (db->Files[fi].HasStream)
+ const CFileItem &file = db->Files[fi];
+
+ if (file.HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[fi];
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
needExtract = true;
+ // decodeSize += file.Size;
}
+
extractStatuses.Add(needExtract);
+ if (needExtract)
+ {
+ sizeToEncode += file.Size;
+ /*
+ numImportantFiles = extractStatuses.Size();
+ importantUnpackSize = decodeSize;
+ */
+ }
}
+ // extractStatuses.DeleteFrom(numImportantFiles);
+
unsigned startPackIndex = newDatabase.PackSizes.Size();
UInt64 curUnpackSize;
{
+
CMyComPtr<ISequentialInStream> sbInStream;
+ CRepackStreamBase *repackBase;
+ CFolderInStream2 *FosSpec2 = NULL;
+
+ CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes;
+ CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
{
- CMyComPtr<ISequentialOutStream> sbOutStream;
- sb.CreateStreams(&sbInStream, &sbOutStream);
- sb.ReInit();
- RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
- }
-
- threadDecoder.InStream = inStream;
- threadDecoder.Folders = (const CFolders *)db;
- threadDecoder.FolderIndex = folderIndex;
- threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
-
- threadDecoder.Start();
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ repackBase = threadDecoder.FosSpec;
+ CMyComPtr<ISequentialOutStream> sbOutStream;
+ sb.CreateStreams(&sbInStream, &sbOutStream);
+ sb.ReInit();
+
+ threadDecoder.FosSpec->_stream = sbOutStream;
+
+ threadDecoder.InStream = inStream;
+ threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
+ threadDecoder.Folders = (const CFolders *)db;
+ threadDecoder.FolderIndex = folderIndex;
+
+ // threadDecoder.UnpackSize = importantUnpackSize;
+ // threadDecoder.send_UnpackSize = true;
+ }
+ else
+ #endif
+ {
+ FosSpec2 = new CFolderInStream2;
+ FosSpec2->Init();
+ sbInStream = FosSpec2;
+ repackBase = FosSpec2;
+
+ #ifndef _NO_CRYPTO
+ bool isEncrypted = false;
+ bool passwordIsDefined = false;
+ UString password;
+ #endif
+
+ CMyComPtr<ISequentialInStream> decodedStream;
+ HRESULT res = threadDecoder.Decoder.Decode(
+ EXTERNAL_CODECS_LOC_VARS
+ inStream,
+ db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);,
+ *db, folderIndex,
+ // &importantUnpackSize, // *unpackSize
+ NULL, // *unpackSize : FULL unpack
+
+ NULL, // *outStream
+ NULL, // *compressProgress
+ &decodedStream
+
+ _7Z_DECODER_CRYPRO_VARS
+ #ifndef _7ZIP_ST
+ , false // mtMode
+ , 1 // numThreads
+ #endif
+ );
- RINOK(encoder.Encode(
+ RINOK(res);
+ if (!decodedStream)
+ return E_FAIL;
+
+ FosSpec2->_inStream = decodedStream;
+ }
+
+ repackBase->_db = db;
+ repackBase->_opCallback = opCallback;
+ repackBase->_extractCallback = extractCallback;
+
+ UInt32 startIndex = db->FolderStartFileIndex[folderIndex];
+ RINOK(repackBase->Init(startIndex, &extractStatuses));
+
+ inStreamSizeCountSpec->_db = db;
+ inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ threadDecoder.Start();
+ }
+ #endif
+ }
+
+
+ HRESULT encodeRes = encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- sbInStream, NULL, &inSizeForReduce,
+ inStreamSizeCount,
+ // NULL,
+ &inSizeForReduce,
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,
- archive.SeqStream, newDatabase.PackSizes, progress));
-
- threadDecoder.WaitExecuteFinish();
- }
+ archive.SeqStream, newDatabase.PackSizes, progress);
- RINOK(threadDecoder.Result);
+ if (encodeRes == k_My_HRESULT_CRC_ERROR)
+ return E_FAIL;
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ // 16.00: hang was fixed : for case if decoding was not finished.
+ // We close CBinderInStream and it calls CStreamBinder::CloseRead()
+ inStreamSizeCount.Release();
+ sbInStream.Release();
+
+ threadDecoder.WaitExecuteFinish();
+
+ HRESULT decodeRes = threadDecoder.Result;
+ // if (res == k_My_HRESULT_CRC_ERROR)
+ if (decodeRes == S_FALSE)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
+ // NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NExtract::NOperationResult::kDataError));
+ }
+ return E_FAIL;
+ }
+ RINOK(decodeRes);
+ if (encodeRes == S_OK)
+ if (sb.ProcessedSize != sizeToEncode)
+ encodeRes = E_FAIL;
+ }
+ else
+ #endif
+ {
+ if (FosSpec2->Result == S_FALSE)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NExtract::NOperationResult::kDataError));
+ }
+ return E_FAIL;
+ }
+ RINOK(FosSpec2->Result);
+ }
+
+ RINOK(encodeRes);
+ RINOK(repackBase->CheckFinishedState());
+
+ if (curUnpackSize != sizeToEncode)
+ return E_FAIL;
+ }
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
lps->OutSize += newDatabase.PackSizes[startPackIndex];
@@ -1144,8 +2221,6 @@ HRESULT Update(
newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
- CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
-
CNum indexInFolder = 0;
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
@@ -1187,14 +2262,21 @@ HRESULT Update(
}
}
+
+ // ---------- Compress files to new solid blocks ----------
+
unsigned numFiles = group.Indices.Size();
if (numFiles == 0)
continue;
CRecordVector<CRefItem> refItems;
refItems.ClearAndSetSize(numFiles);
- bool sortByType = (numSolidFiles > 1);
+ bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
+
+ unsigned i;
+
for (i = 0; i < numFiles; i++)
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
+
CSortParam sortParam;
// sortParam.TreeFolders = &treeFolders;
sortParam.SortByType = sortByType;
@@ -1222,10 +2304,11 @@ HRESULT Update(
for (i = 0; i < numFiles;)
{
UInt64 totalSize = 0;
- int numSubFiles;
- UString prevExtension;
- for (numSubFiles = 0; i + numSubFiles < numFiles &&
- numSubFiles < numSolidFiles; numSubFiles++)
+ unsigned numSubFiles;
+
+ const wchar_t *prevExtension = NULL;
+
+ for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++)
{
const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];
totalSize += ui.Size;
@@ -1233,17 +2316,21 @@ HRESULT Update(
break;
if (options.SolidExtension)
{
- UString ext = ui.GetExtension();
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ int dotPos = ui.Name.ReverseFind_Dot();
+ const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1);
if (numSubFiles == 0)
prevExtension = ext;
- else
- if (!ext.IsEqualToNoCase(prevExtension))
- break;
+ else if (!StringsAreEqualNoCase(ext, prevExtension))
+ break;
}
}
+
if (numSubFiles < 1)
numSubFiles = 1;
+ RINOK(lps->SetCur());
+
CFolderInStream *inStreamSpec = new CFolderInStream;
CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
@@ -1252,10 +2339,15 @@ HRESULT Update(
UInt64 curFolderUnpackSize;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- solidInStream, NULL, &inSizeForReduce,
+ solidInStream,
+ // NULL,
+ &inSizeForReduce,
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize,
archive.SeqStream, newDatabase.PackSizes, progress));
+ if (!inStreamSpec->WasFinished())
+ return E_FAIL;
+
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
lps->OutSize += newDatabase.PackSizes[startPackIndex];
@@ -1263,9 +2355,11 @@ HRESULT Update(
// for ()
// newDatabase.PackCRCsDefined.Add(false);
// newDatabase.PackCRCs.Add(0);
-
+
CNum numUnpackStreams = 0;
- for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
+ UInt64 skippedSize = 0;
+
+ for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)
{
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
CFileItem file;
@@ -1290,12 +2384,15 @@ HRESULT Update(
*/
if (!inStreamSpec->Processed[subIndex])
{
+ skippedSize += ui.Size;
continue;
- // file.Name += L".locked";
+ // file.Name.AddAscii(".locked");
}
file.Crc = inStreamSpec->CRCs[subIndex];
file.Size = inStreamSpec->Sizes[subIndex];
+
+ // if (file.Size >= 0) // test purposes
if (file.Size != 0)
{
file.CrcDefined = true;
@@ -1307,6 +2404,7 @@ HRESULT Update(
file.CrcDefined = false;
file.HasStream = false;
}
+
/*
file.Parent = ui.ParentFolderIndex;
if (ui.TreeFolderIndex >= 0)
@@ -1316,20 +2414,23 @@ HRESULT Update(
*/
newDatabase.AddFile(file, file2, name);
}
+
// numUnpackStreams = 0 is very bad case for locked files
// v3.13 doesn't understand it.
newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
i += numSubFiles;
+
+ if (skippedSize != 0 && complexity >= skippedSize)
+ {
+ complexity -= skippedSize;
+ RINOK(updateCallback->SetTotal(complexity));
+ }
}
}
- if (folderRefIndex != folderRefs.Size())
- return E_FAIL;
-
RINOK(lps->SetCur());
/*
- folderRefs.ClearAndFree();
fileIndexToUpdateIndexMap.ClearAndFree();
groups.ClearAndFree();
*/
@@ -1350,13 +2451,18 @@ HRESULT Update(
{
const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];
size_t size = buf.GetCapacity();
- memcpy(newDatabase.SecureBuf + pos, buf, size);
+ if (size != 0)
+ memcpy(newDatabase.SecureBuf + pos, buf, size);
newDatabase.SecureSizes.Add((UInt32)size);
pos += size;
}
}
*/
newDatabase.ReserveDown();
+
+ if (opCallback)
+ RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader));
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index 070bc30..06a0b05 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -65,6 +65,7 @@ struct CUpdateItem
// int SecureIndex; // 0 means (no_security)
bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }
+ // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes
CUpdateItem():
// ParentSortIndex(-1),
@@ -77,26 +78,44 @@ struct CUpdateItem
MTimeDefined(false)
// SecureIndex(0)
{}
- void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };
+ void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
- int GetExtensionPos() const;
- UString GetExtension() const;
+ // unsigned GetExtensionPos() const;
+ // UString GetExtension() const;
};
struct CUpdateOptions
{
const CCompressionMethodMode *Method;
const CCompressionMethodMode *HeaderMethod;
- bool UseFilters;
- bool MaxFilter;
+ bool UseFilters; // use additional filters for some files
+ bool MaxFilter; // use BCJ2 filter instead of BCJ
+ int AnalysisLevel;
CHeaderOptions HeaderOptions;
UInt64 NumSolidFiles;
UInt64 NumSolidBytes;
bool SolidExtension;
+
+ bool UseTypeSorting;
+
bool RemoveSfxBlock;
- bool VolumeMode;
+ bool MultiThreadMixer;
+
+ CUpdateOptions():
+ Method(NULL),
+ HeaderMethod(NULL),
+ UseFilters(false),
+ MaxFilter(false),
+ AnalysisLevel(-1),
+ NumSolidFiles((UInt64)(Int64)(-1)),
+ NumSolidBytes((UInt64)(Int64)(-1)),
+ SolidExtension(false),
+ UseTypeSorting(true),
+ RemoveSfxBlock(false),
+ MultiThreadMixer(true)
+ {}
};
HRESULT Update(