mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 22:06:59 -06:00
15.05
This commit is contained in:
committed by
Kornel Lesiński
parent
0713a3ab80
commit
54490d51d5
@@ -350,14 +350,6 @@ SOURCE=..\Common\CoderMixer2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\CoderMixer2MT.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\CoderMixer2MT.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\CrossThreadProgress.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -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
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -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,284 @@ 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];
|
||||
|
||||
|
||||
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 +370,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 +381,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,9 +390,13 @@ 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++)
|
||||
{
|
||||
@@ -288,56 +409,129 @@ HRESULT CDecoder::Decode(
|
||||
}
|
||||
#endif
|
||||
|
||||
coderIndex++;
|
||||
|
||||
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];
|
||||
|
||||
for (j = 0; j < numInStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
|
||||
if (bindPairIndex >= 0)
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
|
||||
else
|
||||
CMyComPtr<ICompressSetFinishMode> setFinishMode;
|
||||
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
|
||||
if (setFinishMode)
|
||||
{
|
||||
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
|
||||
if (index < 0)
|
||||
return S_FALSE; // check it
|
||||
packSizes[j] = packPositions[index + 1] - packPositions[index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
|
||||
}
|
||||
}
|
||||
|
||||
_mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
|
||||
}
|
||||
UInt32 mainCoder, temp;
|
||||
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
|
||||
UInt32 numStreams = (UInt32)coderInfo.NumStreams;
|
||||
|
||||
CObjArray<UInt64> packSizes(numStreams);
|
||||
CObjArray<const UInt64 *> packSizesPointers(numStreams);
|
||||
|
||||
for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
|
||||
|
||||
if (bond >= 0)
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
|
||||
else
|
||||
{
|
||||
int index = folderInfo.Find_in_PackStreams(packStreamIndex);
|
||||
if (index < 0)
|
||||
return E_NOTIMPL;
|
||||
packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
|
||||
/*
|
||||
else
|
||||
_mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
|
||||
*/
|
||||
const UInt64 *unpackSizesPointer =
|
||||
(unpackSize && i == bindInfo.UnpackCoder) ?
|
||||
unpackSize :
|
||||
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
|
||||
|
||||
_mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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 _multiThread;
|
||||
#ifdef _ST_MODE
|
||||
NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
|
||||
bool _useMixerMT;
|
||||
|
||||
#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
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
// bindInfo.CoderMethodIDs.Clear();
|
||||
// folder.OutStreams.Clear();
|
||||
folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < bindInfo.BindPairs.Size(); i++)
|
||||
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;)
|
||||
{
|
||||
CBindPair &bp = folder.BindPairs[i];
|
||||
const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
|
||||
bp.InIndex = mixerBp.InIndex;
|
||||
bp.OutIndex = mixerBp.OutIndex;
|
||||
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;
|
||||
}
|
||||
}
|
||||
folder.Coders.SetSize(bindInfo.Coders.Size());
|
||||
for (i = 0; i < bindInfo.Coders.Size(); i++)
|
||||
}
|
||||
|
||||
void CEncoder::SetFolder(CFolder &folder)
|
||||
{
|
||||
folder.Bonds.SetSize(_bindInfo.Bonds.Size());
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _bindInfo.Bonds.Size(); i++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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));
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_options.MultiThreadMixer)
|
||||
#endif
|
||||
{
|
||||
_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 (i, _options.Methods)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
CCoderInfo &encodingInfo = _codersInfo.AddNew();
|
||||
encodingInfo.MethodID = methodFull.Id;
|
||||
CMyComPtr<ICompressCoder> encoder;
|
||||
CMyComPtr<ICompressCoder2> encoder2;
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
_mixer->SelectMainCoder(false);
|
||||
UInt32 mainCoder = _mixer->MainCoderIndex;
|
||||
|
||||
bool useMtProgress = false;
|
||||
if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
|
||||
{
|
||||
#ifdef _7ZIP_ST
|
||||
if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
|
||||
#endif
|
||||
useMtProgress = true;
|
||||
}
|
||||
|
||||
if (useMtProgress)
|
||||
{
|
||||
mtProgressSpec = new CMtEncMultiProgress;
|
||||
mtProgress = mtProgressSpec;
|
||||
mtProgressSpec->Init(compressProgress);
|
||||
|
||||
mtOutStreamNotifySpec = new CSequentialOutMtNotify;
|
||||
mtOutStreamNotify = mtOutStreamNotifySpec;
|
||||
mtOutStreamNotifySpec->_stream = outStream;
|
||||
mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
|
||||
|
||||
FOR_VECTOR(i, tempBufferSpecs)
|
||||
{
|
||||
tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 progressIndex = mainCoderIndex;
|
||||
|
||||
for (i = 0; i + 1 < _codersInfo.Size(); i++)
|
||||
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
{
|
||||
UInt64 m = _codersInfo[i].MethodID;
|
||||
if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
|
||||
progressIndex = i + 1;
|
||||
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
outStreamSizeCount = outStreamSizeCountSpec;
|
||||
outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
}
|
||||
|
||||
_mixerCoderSpec->SetProgressCoderIndex(progressIndex);
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
outStreamPointers.Add(tempBuffers[i - 1]);
|
||||
|
||||
RINOK(_mixer->Code(
|
||||
&inStreamPointer,
|
||||
&outStreamPointers.Front(),
|
||||
mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
|
||||
|
||||
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
|
||||
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
|
||||
|
||||
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
|
||||
|
||||
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 i = _bindInfo.FindStream_in_PackStreams(outIndex);
|
||||
if (i >= 0)
|
||||
_bindInfo.PackStreams.MoveToFront(i);
|
||||
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() {}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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 CMtEncMultiProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
#ifndef _7ZIP_ST
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
|
||||
public:
|
||||
UInt64 OutSize;
|
||||
|
||||
CMtEncMultiProgress(): OutSize(0) {}
|
||||
|
||||
void Init(ICompressProgressInfo *progress);
|
||||
|
||||
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
|
||||
{
|
||||
NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
|
||||
CMyComPtr<ICompressCoder2> _mixerCoder;
|
||||
|
||||
CObjectVector<CCoderInfo> _codersInfo;
|
||||
#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,
|
||||
|
||||
@@ -2,205 +2,327 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
if (fileIndex != kNumNoIndex)
|
||||
{
|
||||
ExtractStatuses.ClearAndSetSize(1);
|
||||
ExtractStatuses[0] = true;
|
||||
}
|
||||
};
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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));
|
||||
|
||||
CDecoder decoder(
|
||||
#ifdef _ST_MODE
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
// CDecoder1 decoder;
|
||||
|
||||
UInt64 totalPacked = 0;
|
||||
UInt64 totalUnpacked = 0;
|
||||
UInt64 curPacked, curUnpacked;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
|
||||
CDecoder decoder(
|
||||
#ifndef USE_MIXER_ST
|
||||
false
|
||||
#else
|
||||
_useMultiThreadMixer
|
||||
#endif
|
||||
);
|
||||
|
||||
UInt64 curPacked, curUnpacked;
|
||||
|
||||
CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
|
||||
extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
|
||||
|
||||
CFolderOutStream *folderOutStream = new CFolderOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
|
||||
|
||||
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);
|
||||
|
||||
i += numSolidFiles;
|
||||
|
||||
RINOK(result);
|
||||
|
||||
if (efi.FileIndex != kNumNoIndex)
|
||||
// to test solid block with zero unpacked size we disable that code
|
||||
if (folderOutStream->WasWritingFinished())
|
||||
continue;
|
||||
|
||||
CNum folderIndex = efi.FolderIndex;
|
||||
curPacked = _db.GetFolderFullPackSize(folderIndex);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (extractCallback)
|
||||
@@ -212,50 +334,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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ISequentialInStream> _stream;
|
||||
UInt64 _pos;
|
||||
UInt32 _crc;
|
||||
bool _size_Defined;
|
||||
UInt64 _size;
|
||||
|
||||
const UInt32 *_indexes;
|
||||
unsigned _numFiles;
|
||||
unsigned _index;
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
|
||||
|
||||
bool _currentSizeIsDefined;
|
||||
bool _fileIsOpen;
|
||||
UInt64 _currentSize;
|
||||
UInt64 _filePos;
|
||||
const UInt32 *_fileIndices;
|
||||
UInt32 _numFiles;
|
||||
UInt32 _fileIndex;
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,149 +1,3 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,56 +3,4 @@
|
||||
#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
|
||||
|
||||
@@ -150,22 +150,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 +176,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 +365,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
|
||||
@@ -500,17 +490,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 +503,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 +515,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
temp[--pos] = '.';
|
||||
temp[--pos] = '.';
|
||||
}
|
||||
|
||||
return PropVarEm_Set_Str(prop, temp + pos);
|
||||
// }
|
||||
}
|
||||
@@ -555,7 +538,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 +591,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 +602,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 +652,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 +667,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 +678,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 +698,7 @@ STDMETHODIMP CHandler::Close()
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
_password.Empty();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
@@ -715,11 +707,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++)
|
||||
{
|
||||
@@ -732,7 +725,8 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsPrefixedBy(L"mt"))
|
||||
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
|
||||
continue;
|
||||
|
||||
@@ -18,16 +18,6 @@
|
||||
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
|
||||
@@ -64,7 +54,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 +109,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 +123,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
|
||||
|
||||
@@ -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;
|
||||
@@ -517,18 +531,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 +558,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 +566,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 +594,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;
|
||||
/*
|
||||
@@ -587,7 +614,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options.NumSolidBytes = _numSolidBytes;
|
||||
options.SolidExtension = _solidExtension;
|
||||
options.RemoveSfxBlock = _removeSfxBlock;
|
||||
options.VolumeMode = _volumeMode;
|
||||
// options.VolumeMode = _volumeMode;
|
||||
|
||||
options.MultiThreadMixer = _useMultiThreadMixer;
|
||||
|
||||
COutArchive archive;
|
||||
CArchiveDatabaseOut newDatabase;
|
||||
@@ -635,20 +664,20 @@ 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);
|
||||
srcString.DeleteFrontal(index);
|
||||
if (srcString[0] == 's')
|
||||
{
|
||||
srcString.Delete(0);
|
||||
int index = ParseStringToUInt32(srcString, stream);
|
||||
if (index == 0)
|
||||
return E_INVALIDARG;
|
||||
srcString.Delete(0, index);
|
||||
srcString.DeleteFrontal(index);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -667,7 +696,10 @@ void COutHandler::InitProps()
|
||||
Write_ATime.Init();
|
||||
Write_MTime.Init();
|
||||
|
||||
_volumeMode = false;
|
||||
_useMultiThreadMixer = true;
|
||||
|
||||
// _volumeMode = false;
|
||||
|
||||
InitSolid();
|
||||
}
|
||||
|
||||
@@ -762,7 +794,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 +819,17 @@ 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("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 +846,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 +869,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, _bonds)
|
||||
{
|
||||
FOR_VECTOR (k, _binds)
|
||||
{
|
||||
CBind &bind = _binds[k];
|
||||
bind.InCoder++;
|
||||
bind.OutCoder++;
|
||||
}
|
||||
_methods.Insert(0, _filterMethod);
|
||||
}
|
||||
|
||||
FOR_VECTOR (k, _binds)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -193,6 +118,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 +145,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 +278,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 +286,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 +313,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 +353,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 +381,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 +398,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 +449,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 +473,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 +532,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 +541,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 +579,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 +635,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 +672,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 +708,7 @@ void CInArchive::ReadUnpackInfo(
|
||||
}
|
||||
}
|
||||
|
||||
if (numOutStreams == 1 && numInStreams == 1)
|
||||
if (numCoders == 1 && numInStreams == 1)
|
||||
{
|
||||
indexOfMainStream = 0;
|
||||
numPackStreams = 1;
|
||||
@@ -767,55 +716,55 @@ void CInArchive::ReadUnpackInfo(
|
||||
else
|
||||
{
|
||||
UInt32 i;
|
||||
if (numOutStreams == 0)
|
||||
ThrowUnsupported();
|
||||
CNum numBindPairs = numOutStreams - 1;
|
||||
if (numInStreams < numBindPairs)
|
||||
ThrowUnsupported();
|
||||
if (numInStreams >= 256 || numOutStreams >= 256)
|
||||
CNum numBonds = numCoders - 1;
|
||||
if (numInStreams < numBonds)
|
||||
ThrowUnsupported();
|
||||
|
||||
InStreamUsed.ClearAndSetSize(numInStreams);
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
InStreamUsed[i] = false;
|
||||
BoolVector_Fill_False(StreamUsed, numInStreams);
|
||||
BoolVector_Fill_False(CoderUsed, numCoders);
|
||||
|
||||
OutStreamUsed.ClearAndSetSize(numOutStreams);
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
OutStreamUsed[i] = false;
|
||||
|
||||
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;
|
||||
packStreamIndex += numPackStreams;
|
||||
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
|
||||
}
|
||||
|
||||
size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
|
||||
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
|
||||
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
|
||||
@@ -1105,13 +1054,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 +1070,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);
|
||||
|
||||
@@ -1208,7 +1157,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;
|
||||
@@ -1396,6 +1345,9 @@ HRESULT CInArchive::ReadHeader(
|
||||
|
||||
type = ReadID(); // Read (NID::kEnd) end of headers
|
||||
|
||||
if (numFiles - numEmptyStreams != unpackSizes.Size())
|
||||
ThrowUnsupported();
|
||||
|
||||
CNum emptyFileIndex = 0;
|
||||
CNum sizeIndex = 0;
|
||||
|
||||
@@ -1403,7 +1355,7 @@ HRESULT CInArchive::ReadHeader(
|
||||
for (i = 0; i < numEmptyStreams; i++)
|
||||
if (antiFileVector[i])
|
||||
numAntiItems++;
|
||||
|
||||
|
||||
for (i = 0; i < numFiles; i++)
|
||||
{
|
||||
CFileItem &file = db.Files[i];
|
||||
@@ -1444,13 +1396,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 +1441,7 @@ void CDbEx::FillLinks()
|
||||
if (indexInFolder != 0)
|
||||
ThrowIncorrect();
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (folderIndex >= NumFolders)
|
||||
|
||||
@@ -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
|
||||
@@ -103,9 +113,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 +158,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 +192,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 +246,8 @@ struct CDbEx: public CDatabase
|
||||
|
||||
// SecureOffsets.Clear();
|
||||
ArcInfo.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
FileIndexToFolderIndexMap.Clear();
|
||||
FolderStartFileIndex.Free();
|
||||
FileIndexToFolderIndexMap.Free();
|
||||
|
||||
HeadersSize = 0;
|
||||
PhySize = 0;
|
||||
@@ -243,22 +255,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 +339,8 @@ class CInArchive
|
||||
|
||||
UInt64 HeadersSize;
|
||||
|
||||
bool _useMixerMT;
|
||||
|
||||
void AddByteStream(const Byte *buffer, size_t size);
|
||||
|
||||
void DeleteByteStream(bool needUpdatePos)
|
||||
@@ -340,7 +354,6 @@ class CInArchive
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
|
||||
@@ -396,7 +409,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();
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
FOR_VECTOR(i, BindPairs)
|
||||
if (BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindBindPairForOutStream(CNum outStreamIndex) const
|
||||
{
|
||||
FOR_VECTOR(i, BindPairs)
|
||||
if (BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindPackStreamArrayIndex(CNum inStreamIndex) const
|
||||
bool IsDecodingSupported() const { return Coders.Size() <= 32; }
|
||||
|
||||
int Find_in_PackStreams(UInt32 packStream) const
|
||||
{
|
||||
FOR_VECTOR(i, PackStreams)
|
||||
if (PackStreams[i] == inStreamIndex)
|
||||
if (PackStreams[i] == packStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GetIndexOfMainOutStream() const
|
||||
int FindBond_for_PackStream(UInt32 packStream) const
|
||||
{
|
||||
for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)
|
||||
if (FindBindPairForOutStream(i) < 0)
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return i;
|
||||
throw 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
int FindBond_for_UnpackStream(UInt32 unpackStream) const
|
||||
{
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].UnpackIndex == unpackStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindOutCoder() const
|
||||
{
|
||||
for (int i = (int)Coders.Size() - 1; i >= 0; i--)
|
||||
if (FindBond_for_UnpackStream(i) < 0)
|
||||
return i;
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace N7z {
|
||||
|
||||
struct CPropMap
|
||||
{
|
||||
UInt64 FilePropID;
|
||||
UInt32 FilePropID;
|
||||
STATPROPSTG StatPROPSTG;
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ static const CPropMap kPropMap[] =
|
||||
{ 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)
|
||||
{
|
||||
@@ -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 STATPROPSTG &st = pr.StatPROPSTG;
|
||||
*propID = st.propid;
|
||||
*varType = st.vt;
|
||||
/*
|
||||
if (st.lpwstrName)
|
||||
*name = ::SysAllocString(st.lpwstrName);
|
||||
else
|
||||
*/
|
||||
*name = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
_stream = stream;
|
||||
_getSubStreamSize = 0;
|
||||
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
|
||||
_size = 0;
|
||||
_getSubStreamSize.Release();
|
||||
_stream = stream;
|
||||
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
|
||||
}
|
||||
UInt64 GetSize() const { return _size; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,18 +78,19 @@ 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;
|
||||
|
||||
@@ -96,7 +98,20 @@ struct CUpdateOptions
|
||||
UInt64 NumSolidBytes;
|
||||
bool SolidExtension;
|
||||
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),
|
||||
RemoveSfxBlock(false),
|
||||
MultiThreadMixer(true)
|
||||
{}
|
||||
};
|
||||
|
||||
HRESULT Update(
|
||||
|
||||
Reference in New Issue
Block a user