diff options
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Common')
31 files changed, 2823 insertions, 0 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer.cpp new file mode 100644 index 000000000..a19f04579 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer.cpp @@ -0,0 +1,19 @@ +// CoderMixer.cpp + +#include "StdAfx.h" + +#include "CoderMixer.h" + +namespace NCoderMixer { + +void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + InSizeAssigned = (inSize != 0); + if (InSizeAssigned) + InSizeValue = *inSize; + OutSizeAssigned = (outSize != 0); + if (OutSizeAssigned) + OutSizeValue = *outSize; +} + +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer.h new file mode 100644 index 000000000..6379dd808 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer.h @@ -0,0 +1,32 @@ +// CoderMixer.h + +#ifndef __CODER_MIXER_H +#define __CODER_MIXER_H + +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer { + +struct CCoderInfo +{ + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ISequentialInStream> InStream; + CMyComPtr<ISequentialOutStream> OutStream; + CMyComPtr<ICompressProgressInfo> Progress; + + UInt64 InSizeValue; + UInt64 OutSizeValue; + bool InSizeAssigned; + bool OutSizeAssigned; + + void ReInit() + { + InSizeAssigned = OutSizeAssigned = false; + } + + void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize); +}; + +} +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp new file mode 100644 index 000000000..0b06a489f --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -0,0 +1,121 @@ +// CoderMixer2.cpp + +#include "StdAfx.h" + +#include "CoderMixer2.h" + +namespace NCoderMixer { + +CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): + _srcBindInfo(srcBindInfo) +{ + srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); + + UInt32 j; + for (j = 0; j < NumSrcInStreams; j++) + { + _srcInToDestOutMap.Add(0); + DestOutToSrcInMap.Add(0); + } + for (j = 0; j < _numSrcOutStreams; j++) + { + _srcOutToDestInMap.Add(0); + _destInToSrcOutMap.Add(0); + } + + UInt32 destInOffset = 0; + UInt32 destOutOffset = 0; + UInt32 srcInOffset = NumSrcInStreams; + UInt32 srcOutOffset = _numSrcOutStreams; + + for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) + { + const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; + + srcInOffset -= srcCoderInfo.NumInStreams; + srcOutOffset -= srcCoderInfo.NumOutStreams; + + UInt32 j; + for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) + { + UInt32 index = srcInOffset + j; + _srcInToDestOutMap[index] = destOutOffset; + DestOutToSrcInMap[destOutOffset] = index; + } + for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) + { + UInt32 index = srcOutOffset + j; + _srcOutToDestInMap[index] = destInOffset; + _destInToSrcOutMap[destInOffset] = index; + } + } +} + +void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) +{ + destBindInfo.Coders.Clear(); + destBindInfo.BindPairs.Clear(); + destBindInfo.InStreams.Clear(); + destBindInfo.OutStreams.Clear(); + + int i; + for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) + { + const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; + CCoderStreamsInfo destCoderInfo; + destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; + destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; + destBindInfo.Coders.Add(destCoderInfo); + } + for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) + { + const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; + CBindPair destBindPair; + destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; + destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; + destBindInfo.BindPairs.Add(destBindPair); + } + for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) + destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); + for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) + destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); +} + +CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): + NumInStreams(numInStreams), + NumOutStreams(numOutStreams) +{ + InSizes.Reserve(NumInStreams); + InSizePointers.Reserve(NumInStreams); + OutSizes.Reserve(NumOutStreams); + OutSizePointers.Reserve(NumOutStreams); +} + +static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, + CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) +{ + sizes.Clear(); + sizePointers.Clear(); + for(UInt32 i = 0; i < numItems; i++) + { + if (srcSizes == 0 || srcSizes[i] == NULL) + { + sizes.Add(0); + sizePointers.Add(NULL); + } + else + { + sizes.Add(*srcSizes[i]); + sizePointers.Add(&sizes.Back()); + } + } +} + +void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, + const UInt64 **outSizes) +{ + SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); + SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); +} + +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h new file mode 100644 index 000000000..a03722d61 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h @@ -0,0 +1,174 @@ +// CoderMixer2.h + +#ifndef __CODER_MIXER2_H +#define __CODER_MIXER2_H + +#include "../../../Common/MyVector.h" +#include "../../../Common/Types.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer { + +struct CBindPair +{ + UInt32 InIndex; + UInt32 OutIndex; +}; + +struct CCoderStreamsInfo +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; +}; + +struct CBindInfo +{ + CRecordVector<CCoderStreamsInfo> Coders; + CRecordVector<CBindPair> BindPairs; + CRecordVector<UInt32> InStreams; + CRecordVector<UInt32> OutStreams; + + void Clear() + { + Coders.Clear(); + BindPairs.Clear(); + InStreams.Clear(); + OutStreams.Clear(); + } + + /* + UInt32 GetCoderStartOutStream(UInt32 coderIndex) const + { + UInt32 numOutStreams = 0; + for (UInt32 i = 0; i < coderIndex; i++) + numOutStreams += Coders[i].NumOutStreams; + return numOutStreams; + } + */ + + + void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const + { + numInStreams = 0; + numOutStreams = 0; + for (int i = 0; i < Coders.Size(); i++) + { + const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; + numInStreams += coderStreamsInfo.NumInStreams; + numOutStreams += coderStreamsInfo.NumOutStreams; + } + } + + int FindBinderForInStream(UInt32 inStream) const + { + for (int i = 0; i < BindPairs.Size(); i++) + if (BindPairs[i].InIndex == inStream) + return i; + return -1; + } + int FindBinderForOutStream(UInt32 outStream) const + { + for (int i = 0; i < BindPairs.Size(); i++) + if (BindPairs[i].OutIndex == outStream) + return i; + return -1; + } + + UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const + { + UInt32 streamIndex = 0; + for (UInt32 i = 0; i < coderIndex; i++) + streamIndex += Coders[i].NumInStreams; + return streamIndex; + } + + UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const + { + UInt32 streamIndex = 0; + for (UInt32 i = 0; i < coderIndex; i++) + streamIndex += Coders[i].NumOutStreams; + return streamIndex; + } + + + void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, + UInt32 &coderStreamIndex) const + { + for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) + { + UInt32 curSize = Coders[coderIndex].NumInStreams; + if (streamIndex < curSize) + { + coderStreamIndex = streamIndex; + return; + } + streamIndex -= curSize; + } + throw 1; + } + void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, + UInt32 &coderStreamIndex) const + { + for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) + { + UInt32 curSize = Coders[coderIndex].NumOutStreams; + if (streamIndex < curSize) + { + coderStreamIndex = streamIndex; + return; + } + streamIndex -= curSize; + } + throw 1; + } +}; + +class CBindReverseConverter +{ + UInt32 _numSrcOutStreams; + NCoderMixer::CBindInfo _srcBindInfo; + CRecordVector<UInt32> _srcInToDestOutMap; + CRecordVector<UInt32> _srcOutToDestInMap; + CRecordVector<UInt32> _destInToSrcOutMap; +public: + UInt32 NumSrcInStreams; + CRecordVector<UInt32> DestOutToSrcInMap; + + CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); + void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); +}; + +struct CCoderInfo2 +{ + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ICompressCoder2> Coder2; + UInt32 NumInStreams; + UInt32 NumOutStreams; + + CRecordVector<UInt64> InSizes; + CRecordVector<UInt64> OutSizes; + CRecordVector<const UInt64 *> InSizePointers; + CRecordVector<const UInt64 *> OutSizePointers; + + CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); + void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); + + HRESULT QueryInterface(REFGUID iid, void** pp) const + { + IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; + return p->QueryInterface(iid, pp); + } +}; + +class CCoderMixer2 +{ +public: + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; + virtual void ReInit() = 0; + virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; +}; + +} +#endif + diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp new file mode 100644 index 000000000..d76450bd1 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -0,0 +1,240 @@ +// CoderMixer2MT.cpp + +#include "StdAfx.h" + +#include "CoderMixer2MT.h" + +namespace NCoderMixer { + +CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): + CCoderInfo2(numInStreams, numOutStreams) +{ + InStreams.Reserve(NumInStreams); + InStreamPointers.Reserve(NumInStreams); + OutStreams.Reserve(NumOutStreams); + OutStreamPointers.Reserve(NumOutStreams); +} + +void CCoder2::Execute() { Code(NULL); } + +void CCoder2::Code(ICompressProgressInfo *progress) +{ + InStreamPointers.Clear(); + OutStreamPointers.Clear(); + UInt32 i; + for (i = 0; i < NumInStreams; i++) + { + if (InSizePointers[i] != NULL) + InSizePointers[i] = &InSizes[i]; + InStreamPointers.Add((ISequentialInStream *)InStreams[i]); + } + for (i = 0; i < NumOutStreams; i++) + { + if (OutSizePointers[i] != NULL) + OutSizePointers[i] = &OutSizes[i]; + OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); + } + if (Coder) + Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], + InSizePointers[0], OutSizePointers[0], progress); + else + Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, + &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); + { + int i; + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); + } +} + +static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, + CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) +{ + sizes.Clear(); + sizePointers.Clear(); + for (UInt32 i = 0; i < numItems; i++) + { + if (srcSizes == 0 || srcSizes[i] == NULL) + { + sizes.Add(0); + sizePointers.Add(NULL); + } + else + { + sizes.Add(*srcSizes[i]); + sizePointers.Add(&sizes.Back()); + } + } +} + + +void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) +{ + SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); + SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); +} + +////////////////////////////////////// +// CCoderMixer2MT + +HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) +{ + _bindInfo = bindInfo; + _streamBinders.Clear(); + for (int i = 0; i < _bindInfo.BindPairs.Size(); i++) + { + _streamBinders.Add(CStreamBinder()); + RINOK(_streamBinders.Back().CreateEvents()); + } + return S_OK; +} + +void CCoderMixer2MT::AddCoderCommon() +{ + const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; + CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); + _coders.Add(threadCoderInfo); +} + +void CCoderMixer2MT::AddCoder(ICompressCoder *coder) +{ + AddCoderCommon(); + _coders.Back().Coder = coder; +} + +void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) +{ + AddCoderCommon(); + _coders.Back().Coder2 = coder; +} + + +void CCoderMixer2MT::ReInit() +{ + for (int i = 0; i < _streamBinders.Size(); i++) + _streamBinders[i].ReInit(); +} + + +HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) +{ + /* + if (_coders.Size() != _bindInfo.Coders.Size()) + throw 0; + */ + int i; + for (i = 0; i < _coders.Size(); i++) + { + CCoder2 &coderInfo = _coders[i]; + const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; + coderInfo.InStreams.Clear(); + UInt32 j; + for (j = 0; j < coderStreamsInfo.NumInStreams; j++) + coderInfo.InStreams.Add(NULL); + coderInfo.OutStreams.Clear(); + for (j = 0; j < coderStreamsInfo.NumOutStreams; j++) + coderInfo.OutStreams.Add(NULL); + } + + for (i = 0; i < _bindInfo.BindPairs.Size(); i++) + { + const CBindPair &bindPair = _bindInfo.BindPairs[i]; + UInt32 inCoderIndex, inCoderStreamIndex; + UInt32 outCoderIndex, outCoderStreamIndex; + _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); + _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); + + _streamBinders[i].CreateStreams( + &_coders[inCoderIndex].InStreams[inCoderStreamIndex], + &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); + + CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize; + _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); + _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize); + if (inSetSize && outSetSize) + { + const UInt32 kBufSize = 1 << 19; + inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize); + outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize); + } + } + + for (i = 0; i < _bindInfo.InStreams.Size(); i++) + { + UInt32 inCoderIndex, inCoderStreamIndex; + _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); + _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; + } + + for (i = 0; i < _bindInfo.OutStreams.Size(); i++) + { + UInt32 outCoderIndex, outCoderStreamIndex; + _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); + _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; + } + return S_OK; +} + +HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) +{ + for (int i = 0; i < _coders.Size(); i++) + if (_coders[i].Result == code) + return code; + return S_OK; +} + +STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, + const UInt64 ** /* inSizes */, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 ** /* outSizes */, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || + numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) + return E_INVALIDARG; + + Init(inStreams, outStreams); + + int i; + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + { + RINOK(_coders[i].Create()); + } + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].Start(); + + _coders[_progressCoderIndex].Code(progress); + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].WaitFinish(); + + RINOK(ReturnIfError(E_ABORT)); + RINOK(ReturnIfError(E_OUTOFMEMORY)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK && result != E_FAIL && result != S_FALSE) + return result; + } + + RINOK(ReturnIfError(S_FALSE)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK) + return result; + } + return S_OK; +} + +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h new file mode 100644 index 000000000..d1c7f4d07 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -0,0 +1,80 @@ +// CoderMixer2MT.h + +#ifndef __CODER_MIXER2_MT_H +#define __CODER_MIXER2_MT_H + +#include "CoderMixer2.h" +#include "../../../Common/MyCom.h" +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" + +namespace NCoderMixer { + +struct CCoder2: public CCoderInfo2, public CVirtThread +{ + HRESULT Result; + CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; + CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; + CRecordVector<ISequentialInStream*> InStreamPointers; + CRecordVector<ISequentialOutStream*> OutStreamPointers; + + CCoder2(UInt32 numInStreams, UInt32 numOutStreams); + void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); + virtual void Execute(); + void Code(ICompressProgressInfo *progress); +}; + + +/* + SetBindInfo() + for each coder + AddCoder[2]() + SetProgressIndex(UInt32 coderIndex); + + for each file + { + ReInit() + for each coder + SetCoderInfo + Code + } +*/ + +class CCoderMixer2MT: + public ICompressCoder2, + public CCoderMixer2, + public CMyUnknownImp +{ + CBindInfo _bindInfo; + CObjectVector<CStreamBinder> _streamBinders; + int _progressCoderIndex; + + void AddCoderCommon(); + HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); + HRESULT ReturnIfError(HRESULT code); +public: + CObjectVector<CCoder2> _coders; + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + + HRESULT SetBindInfo(const CBindInfo &bindInfo); + void AddCoder(ICompressCoder *coder); + void AddCoder2(ICompressCoder2 *coder); + void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) + { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } + UInt64 GetWriteProcessedSize(UInt32 binderIndex) const + { return _streamBinders[binderIndex].ProcessedSize; } +}; + +} +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2ST.cpp new file mode 100644 index 000000000..a59ce5fc0 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -0,0 +1,239 @@ +// CoderMixer2ST.cpp + +#include "StdAfx.h" + +#include "CoderMixer2ST.h" + +namespace NCoderMixer2 { + +CCoderMixer2ST::CCoderMixer2ST() {} + +CCoderMixer2ST::~CCoderMixer2ST(){ } + +HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo) +{ + _bindInfo = bindInfo; + return S_OK; +} + +void CCoderMixer2ST::AddCoderCommon(bool isMain) +{ + const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()]; + _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain)); +} + +void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain) +{ + AddCoderCommon(isMain); + _coders.Back().Coder = coder; +} + +void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain) +{ + AddCoderCommon(isMain); + _coders.Back().Coder2 = coder; +} + +void CCoderMixer2ST::ReInit() { } + +HRESULT CCoderMixer2ST::GetInStream( + ISequentialInStream **inStreams, const UInt64 **inSizes, + UInt32 streamIndex, ISequentialInStream **inStreamRes) +{ + CMyComPtr<ISequentialInStream> seqInStream; + int i; + for(i = 0; i < _bindInfo.InStreams.Size(); i++) + if (_bindInfo.InStreams[i] == streamIndex) + { + seqInStream = inStreams[i]; + *inStreamRes = seqInStream.Detach(); + return S_OK; + } + int binderIndex = _bindInfo.FindBinderForInStream(streamIndex); + if (binderIndex < 0) + return E_INVALIDARG; + + UInt32 coderIndex, coderStreamIndex; + _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex, + coderIndex, coderStreamIndex); + + CCoderInfo &coder = _coders[coderIndex]; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream); + if (!seqInStream) + return E_NOTIMPL; + + UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex); + + CMyComPtr<ICompressSetInStream> setInStream; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream); + if (!setInStream) + return E_NOTIMPL; + + if (coder.NumInStreams > 1) + return E_NOTIMPL; + for (i = 0; i < (int)coder.NumInStreams; i++) + { + CMyComPtr<ISequentialInStream> seqInStream2; + RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2)); + RINOK(setInStream->SetInStream(seqInStream2)); + } + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + +HRESULT CCoderMixer2ST::GetOutStream( + ISequentialOutStream **outStreams, const UInt64 **outSizes, + UInt32 streamIndex, ISequentialOutStream **outStreamRes) +{ + CMyComPtr<ISequentialOutStream> seqOutStream; + int i; + for(i = 0; i < _bindInfo.OutStreams.Size(); i++) + if (_bindInfo.OutStreams[i] == streamIndex) + { + seqOutStream = outStreams[i]; + *outStreamRes = seqOutStream.Detach(); + return S_OK; + } + int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex); + if (binderIndex < 0) + return E_INVALIDARG; + + UInt32 coderIndex, coderStreamIndex; + _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex, + coderIndex, coderStreamIndex); + + CCoderInfo &coder = _coders[coderIndex]; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream); + if (!seqOutStream) + return E_NOTIMPL; + + UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); + + CMyComPtr<ICompressSetOutStream> setOutStream; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (!setOutStream) + return E_NOTIMPL; + + if (coder.NumOutStreams > 1) + return E_NOTIMPL; + for (i = 0; i < (int)coder.NumOutStreams; i++) + { + CMyComPtr<ISequentialOutStream> seqOutStream2; + RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2)); + RINOK(setOutStream->SetOutStream(seqOutStream2)); + } + *outStreamRes = seqOutStream.Detach(); + return S_OK; +} + + +STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || + numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) + return E_INVALIDARG; + + // Find main coder + int _mainCoderIndex = -1; + int i; + for (i = 0; i < _coders.Size(); i++) + if (_coders[i].IsMain) + { + _mainCoderIndex = i; + break; + } + if (_mainCoderIndex < 0) + for (i = 0; i < _coders.Size(); i++) + if (_coders[i].NumInStreams > 1) + { + if (_mainCoderIndex >= 0) + return E_NOTIMPL; + _mainCoderIndex = i; + } + if (_mainCoderIndex < 0) + _mainCoderIndex = 0; + + // _mainCoderIndex = 0; + // _mainCoderIndex = _coders.Size() - 1; + CCoderInfo &mainCoder = _coders[_mainCoderIndex]; + + CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; + CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; + UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex); + UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex); + for (i = 0; i < (int)mainCoder.NumInStreams; i++) + { + CMyComPtr<ISequentialInStream> seqInStream; + RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream)); + seqInStreams.Add(seqInStream); + } + for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + { + CMyComPtr<ISequentialOutStream> seqOutStream; + RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream)); + seqOutStreams.Add(seqOutStream); + } + CRecordVector< ISequentialInStream * > seqInStreamsSpec; + CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; + for (i = 0; i < (int)mainCoder.NumInStreams; i++) + seqInStreamsSpec.Add(seqInStreams[i]); + for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + seqOutStreamsSpec.Add(seqOutStreams[i]); + + for (i = 0; i < _coders.Size(); i++) + { + if (i == _mainCoderIndex) + continue; + CCoderInfo &coder = _coders[i]; + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; + coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + if (setOutStreamSize) + { + RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0])); + } + } + if (mainCoder.Coder) + { + RINOK(mainCoder.Coder->Code( + seqInStreamsSpec[0], seqOutStreamsSpec[0], + mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0], + progress)); + } + else + { + RINOK(mainCoder.Coder2->Code( + &seqInStreamsSpec.Front(), + &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams, + &seqOutStreamsSpec.Front(), + &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams, + progress)); + } + CMyComPtr<IOutStreamFlush> flush; + seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + return flush->Flush(); + return S_OK; +} + +/* +UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const +{ + return _streamBinders[binderIndex].ProcessedSize; +} +*/ + +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2ST.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2ST.h new file mode 100644 index 000000000..a4ea7e80d --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2ST.h @@ -0,0 +1,88 @@ +// CoderMixer2ST.h + +#ifndef __CODER_MIXER2_ST_H +#define __CODER_MIXER2_ST_H + +#include "CoderMixer2.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer2 { + +// SetBindInfo() +// for each coder +// { +// AddCoder[2]() +// } +// +// for each file +// { +// ReInit() +// for each coder +// { +// SetCoderInfo +// } +// SetProgressIndex(UInt32 coderIndex); +// Code +// } + +struct CSTCoderInfo: public CCoderInfo +{ + bool IsMain; + CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain): + CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {} +}; + +class CCoderMixer2ST: + public ICompressCoder2, + public CCoderMixer2, + public CMyUnknownImp +{ + MY_UNKNOWN_IMP + + HRESULT GetInStream( + ISequentialInStream **inStreams, const UInt64 **inSizes, + UInt32 streamIndex, ISequentialInStream **inStreamRes); + HRESULT GetOutStream( + ISequentialOutStream **outStreams, const UInt64 **outSizes, + UInt32 streamIndex, ISequentialOutStream **outStreamRes); +public: + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + + CCoderMixer2ST(); + ~CCoderMixer2ST(); + void AddCoderCommon(bool isMain); + void AddCoder(ICompressCoder *coder, bool isMain); + void AddCoder2(ICompressCoder2 *coder, bool isMain); + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) + { + { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } + } + + void SetProgressCoderIndex(UInt32 /*coderIndex*/) + { + // _progressCoderIndex = coderIndex; + } + + // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const; + +private: + CBindInfo _bindInfo; + CObjectVector<CSTCoderInfo> _coders; + int _mainCoderIndex; +public: + HRESULT SetBindInfo(const CBindInfo &bindInfo); + +}; + +} +#endif + diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixerMT.cpp new file mode 100644 index 000000000..f43d1612d --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixerMT.cpp @@ -0,0 +1,99 @@ +// CoderMixerMT.cpp + +#include "StdAfx.h" + +#include "CoderMixerMT.h" + +namespace NCoderMixer { + +void CCoder::Execute() { Code(NULL); } + +void CCoder::Code(ICompressProgressInfo *progress) +{ + Result = Coder->Code(InStream, OutStream, + InSizeAssigned ? &InSizeValue : NULL, + OutSizeAssigned ? &OutSizeValue : NULL, + progress); + InStream.Release(); + OutStream.Release(); +} + +void CCoderMixerMT::AddCoder(ICompressCoder *coder) +{ + _coders.Add(CCoder()); + _coders.Back().Coder = coder; +} + +void CCoderMixerMT::ReInit() +{ + for(int i = 0; i < _coders.Size(); i++) + _coders[i].ReInit(); +} + +HRESULT CCoderMixerMT::ReturnIfError(HRESULT code) +{ + for (int i = 0; i < _coders.Size(); i++) + if (_coders[i].Result == code) + return code; + return S_OK; +} + +STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, + ICompressProgressInfo *progress) +{ + _coders.Front().InStream = inStream; + int i; + _coders.Back().OutStream = outStream; + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + { + RINOK(_coders[i].Create()); + } + + _streamBinders.Clear(); + for (i = 0; i + 1 < _coders.Size(); i++) + { + _streamBinders.Add(CStreamBinder()); + CStreamBinder &sb = _streamBinders[i]; + RINOK(sb.CreateEvents()); + sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream); + } + + for(i = 0; i < _streamBinders.Size(); i++) + _streamBinders[i].ReInit(); + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].Start(); + + _coders[_progressCoderIndex].Code(progress); + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].WaitFinish(); + + RINOK(ReturnIfError(E_ABORT)); + RINOK(ReturnIfError(E_OUTOFMEMORY)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK && result != E_FAIL && result != S_FALSE) + return result; + } + + RINOK(ReturnIfError(S_FALSE)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK) + return result; + } + return S_OK; +} + +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixerMT.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixerMT.h new file mode 100644 index 000000000..c70e1829f --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixerMT.h @@ -0,0 +1,69 @@ +// CoderMixerMT.h + +#ifndef __CODER_MIXER_MT_H +#define __CODER_MIXER_MT_H + +#include "../../../Common/MyVector.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" +#include "CoderMixer.h" + +namespace NCoderMixer { + +struct CCoder: public CCoderInfo, public CVirtThread +{ + HRESULT Result; + + virtual void Execute(); + void Code(ICompressProgressInfo *progress); +}; + +/* + for each coder + AddCoder() + SetProgressIndex(UInt32 coderIndex); + + for each file + { + ReInit() + for each coder + SetCoderInfo + Code + } +*/ + + +class CCoderMixerMT: + public ICompressCoder, + public CMyUnknownImp +{ + CObjectVector<CStreamBinder> _streamBinders; + int _progressCoderIndex; + + HRESULT ReturnIfError(HRESULT code); +public: + CObjectVector<CCoder> _coders; + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + void AddCoder(ICompressCoder *coder); + void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize) + { _coders[coderIndex].SetCoderInfo(inSize, outSize); } + + /* + UInt64 GetWriteProcessedSize(UInt32 binderIndex) const + { return _streamBinders[binderIndex].ProcessedSize; } + */ +}; + +} +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.cpp new file mode 100644 index 000000000..a974b54c7 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.cpp @@ -0,0 +1,15 @@ +// CrossThreadProgress.cpp + +#include "StdAfx.h" + +#include "CrossThreadProgress.h" + +STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + InSize = inSize; + OutSize = outSize; + ProgressEvent.Set(); + WaitEvent.Lock(); + return Result; +} + diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.h new file mode 100644 index 000000000..7e0b10538 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/CrossThreadProgress.h @@ -0,0 +1,37 @@ +// CrossThreadProgress.h + +#ifndef __CROSSTHREADPROGRESS_H +#define __CROSSTHREADPROGRESS_H + +#include "../../ICoder.h" +#include "../../../Windows/Synchronization.h" +#include "../../../Common/MyCom.h" + +class CCrossThreadProgress: + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + const UInt64 *InSize; + const UInt64 *OutSize; + HRESULT Result; + NWindows::NSynchronization::CAutoResetEvent ProgressEvent; + NWindows::NSynchronization::CAutoResetEvent WaitEvent; + + HRes Create() + { + RINOK(ProgressEvent.CreateIfNotCreated()); + return WaitEvent.CreateIfNotCreated(); + } + void Init() + { + ProgressEvent.Reset(); + WaitEvent.Reset(); + } + + MY_UNKNOWN_IMP + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp new file mode 100644 index 000000000..54bcfec11 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp @@ -0,0 +1,22 @@ +// DummyOutStream.cpp + +#include "StdAfx.h" + +#include "DummyOutStream.h" + +STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result; + if(!_stream) + { + realProcessedSize = size; + result = S_OK; + } + else + result = _stream->Write(data, size, &realProcessedSize); + _size += realProcessedSize; + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h new file mode 100644 index 000000000..13d5b62ca --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h @@ -0,0 +1,24 @@ +// DummyOutStream.h + +#ifndef __DUMMYOUTSTREAM_H +#define __DUMMYOUTSTREAM_H + +#include "../../IStream.h" +#include "Common/MyCom.h" + +class CDummyOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; +public: + void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _size = 0; } + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + UInt64 GetSize() const { return _size; } +}; + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/FindSignature.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/FindSignature.cpp new file mode 100644 index 000000000..15aa6ceae --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/FindSignature.cpp @@ -0,0 +1,62 @@ +// FindSignature.cpp + +#include "StdAfx.h" + +#include "Common/Buffer.h" + +#include "FindSignature.h" + +#include "../../Common/StreamUtils.h" + +HRESULT FindSignatureInStream(ISequentialInStream *stream, + const Byte *signature, unsigned signatureSize, + const UInt64 *limit, UInt64 &resPos) +{ + resPos = 0; + CByteBuffer byteBuffer2; + byteBuffer2.SetCapacity(signatureSize); + RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize)); + + if (memcmp(byteBuffer2, signature, signatureSize) == 0) + return S_OK; + + const UInt32 kBufferSize = (1 << 16); + CByteBuffer byteBuffer; + byteBuffer.SetCapacity(kBufferSize); + Byte *buffer = byteBuffer; + UInt32 numPrevBytes = signatureSize - 1; + memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes); + resPos = 1; + for (;;) + { + if (limit != NULL) + if (resPos > *limit) + return S_FALSE; + do + { + UInt32 numReadBytes = kBufferSize - numPrevBytes; + UInt32 processedSize; + RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); + numPrevBytes += processedSize; + if (processedSize == 0) + return S_FALSE; + } + while (numPrevBytes < signatureSize); + UInt32 numTests = numPrevBytes - signatureSize + 1; + for (UInt32 pos = 0; pos < numTests; pos++) + { + Byte b = signature[0]; + for (; buffer[pos] != b && pos < numTests; pos++); + if (pos == numTests) + break; + if (memcmp(buffer + pos, signature, signatureSize) == 0) + { + resPos += pos; + return S_OK; + } + } + resPos += numTests; + numPrevBytes -= numTests; + memmove(buffer, buffer + numTests, numPrevBytes); + } +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/FindSignature.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/FindSignature.h new file mode 100644 index 000000000..e15af5732 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/FindSignature.h @@ -0,0 +1,12 @@ +// FindSignature.h + +#ifndef __FINDSIGNATURE_H +#define __FINDSIGNATURE_H + +#include "../../IStream.h" + +HRESULT FindSignatureInStream(ISequentialInStream *stream, + const Byte *signature, unsigned signatureSize, + const UInt64 *limit, UInt64 &resPos); + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp new file mode 100644 index 000000000..70ad47aad --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -0,0 +1,623 @@ +// HandlerOut.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/PropVariant.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/System.h" +#endif + +#include "../../ICoder.h" + +#include "../Common/ParseProperties.h" + +#include "HandlerOut.h" + +using namespace NWindows; + +namespace NArchive { + +static const wchar_t *kCopyMethod = L"Copy"; +static const wchar_t *kLZMAMethodName = L"LZMA"; +static const wchar_t *kLZMA2MethodName = L"LZMA2"; +static const wchar_t *kBZip2MethodName = L"BZip2"; +static const wchar_t *kPpmdMethodName = L"PPMd"; +static const wchar_t *kDeflateMethodName = L"Deflate"; +static const wchar_t *kDeflate64MethodName = L"Deflate64"; + +static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; +static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; + +static const UInt32 kLzmaAlgoX1 = 0; +static const UInt32 kLzmaAlgoX5 = 1; + +static const UInt32 kLzmaDicSizeX1 = 1 << 16; +static const UInt32 kLzmaDicSizeX3 = 1 << 20; +static const UInt32 kLzmaDicSizeX5 = 1 << 24; +static const UInt32 kLzmaDicSizeX7 = 1 << 25; +static const UInt32 kLzmaDicSizeX9 = 1 << 26; + +static const UInt32 kLzmaFastBytesX1 = 32; +static const UInt32 kLzmaFastBytesX7 = 64; + +static const UInt32 kPpmdMemSizeX1 = (1 << 22); +static const UInt32 kPpmdMemSizeX5 = (1 << 24); +static const UInt32 kPpmdMemSizeX7 = (1 << 26); +static const UInt32 kPpmdMemSizeX9 = (192 << 20); + +static const UInt32 kPpmdOrderX1 = 4; +static const UInt32 kPpmdOrderX5 = 6; +static const UInt32 kPpmdOrderX7 = 16; +static const UInt32 kPpmdOrderX9 = 32; + +static const UInt32 kDeflateAlgoX1 = 0; +static const UInt32 kDeflateAlgoX5 = 1; + +static const UInt32 kDeflateFastBytesX1 = 32; +static const UInt32 kDeflateFastBytesX7 = 64; +static const UInt32 kDeflateFastBytesX9 = 128; + +static const UInt32 kDeflatePassesX1 = 1; +static const UInt32 kDeflatePassesX7 = 3; +static const UInt32 kDeflatePassesX9 = 10; + +static const UInt32 kBZip2NumPassesX1 = 1; +static const UInt32 kBZip2NumPassesX7 = 2; +static const UInt32 kBZip2NumPassesX9 = 7; + +static const UInt32 kBZip2DicSizeX1 = 100000; +static const UInt32 kBZip2DicSizeX3 = 500000; +static const UInt32 kBZip2DicSizeX5 = 900000; + +static const wchar_t *kDefaultMethodName = kLZMAMethodName; + +static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; +static const UInt32 kDictionaryForHeaders = 1 << 20; +static const UInt32 kNumFastBytesForHeaders = 273; +static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; + +static bool AreEqual(const UString &methodName, const wchar_t *s) + { return (methodName.CompareNoCase(s) == 0); } + +bool COneMethodInfo::IsLzma() const +{ + return + AreEqual(MethodName, kLZMAMethodName) || + AreEqual(MethodName, kLZMA2MethodName); +} + +static inline bool IsBZip2Method(const UString &methodName) + { return AreEqual(methodName, kBZip2MethodName); } + +static inline bool IsPpmdMethod(const UString &methodName) + { return AreEqual(methodName, kPpmdMethodName); } + +static inline bool IsDeflateMethod(const UString &methodName) +{ + return + AreEqual(methodName, kDeflateMethodName) || + AreEqual(methodName, kDeflate64MethodName); +} + +struct CNameToPropID +{ + PROPID PropID; + VARTYPE VarType; + const wchar_t *Name; +}; + +static CNameToPropID g_NameToPropID[] = +{ + { NCoderPropID::kBlockSize, VT_UI4, L"C" }, + { NCoderPropID::kDictionarySize, VT_UI4, L"D" }, + { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" }, + + { NCoderPropID::kOrder, VT_UI4, L"O" }, + { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, + { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, + { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, + { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, + + { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, + { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, + { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, + { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, + { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, + { NCoderPropID::kNumThreads, VT_UI4, L"mt" }, + { NCoderPropID::kDefaultProp, VT_UI4, L"" } +}; + +static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) +{ + if (varType == srcProp.vt) + { + destProp = srcProp; + return true; + } + if (varType == VT_UI1) + { + if (srcProp.vt == VT_UI4) + { + UInt32 value = srcProp.ulVal; + if (value > 0xFF) + return false; + destProp = (Byte)value; + return true; + } + } + else if (varType == VT_BOOL) + { + bool res; + if (SetBoolProperty(res, srcProp) != S_OK) + return false; + destProp = res; + return true; + } + return false; +} + +static int FindPropIdExact(const UString &name) +{ + for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) + return i; + return -1; +} + +static int FindPropIdStart(const UString &name) +{ + for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + { + UString t = g_NameToPropID[i].Name; + if (t.CompareNoCase(name.Left(t.Length())) == 0) + return i; + } + return -1; +} + +static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value) +{ + for (int j = 0; j < m.Props.Size(); j++) + if (m.Props[j].Id == propID) + return; + CProp prop; + prop.Id = propID; + prop.Value = value; + m.Props.Add(prop); +} + +void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ) +{ + UInt32 level = _level; + if (oneMethodInfo.MethodName.IsEmpty()) + oneMethodInfo.MethodName = kDefaultMethodName; + + if (oneMethodInfo.IsLzma()) + { + UInt32 dicSize = + (level >= 9 ? kLzmaDicSizeX9 : + (level >= 7 ? kLzmaDicSizeX7 : + (level >= 5 ? kLzmaDicSizeX5 : + (level >= 3 ? kLzmaDicSizeX3 : + kLzmaDicSizeX1)))); + + UInt32 algo = + (level >= 5 ? kLzmaAlgoX5 : + kLzmaAlgoX1); + + UInt32 fastBytes = + (level >= 7 ? kLzmaFastBytesX7 : + kLzmaFastBytesX1); + + const wchar_t *matchFinder = + (level >= 5 ? kLzmaMatchFinderX5 : + kLzmaMatchFinderX1); + + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); + #ifndef _7ZIP_ST + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + #endif + } + else if (IsDeflateMethod(oneMethodInfo.MethodName)) + { + UInt32 fastBytes = + (level >= 9 ? kDeflateFastBytesX9 : + (level >= 7 ? kDeflateFastBytesX7 : + kDeflateFastBytesX1)); + + UInt32 numPasses = + (level >= 9 ? kDeflatePassesX9 : + (level >= 7 ? kDeflatePassesX7 : + kDeflatePassesX1)); + + UInt32 algo = + (level >= 5 ? kDeflateAlgoX5 : + kDeflateAlgoX1); + + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + } + else if (IsBZip2Method(oneMethodInfo.MethodName)) + { + UInt32 numPasses = + (level >= 9 ? kBZip2NumPassesX9 : + (level >= 7 ? kBZip2NumPassesX7 : + kBZip2NumPassesX1)); + + UInt32 dicSize = + (level >= 5 ? kBZip2DicSizeX5 : + (level >= 3 ? kBZip2DicSizeX3 : + kBZip2DicSizeX1)); + + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + #ifndef _7ZIP_ST + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + #endif + } + else if (IsPpmdMethod(oneMethodInfo.MethodName)) + { + UInt32 useMemSize = + (level >= 9 ? kPpmdMemSizeX9 : + (level >= 7 ? kPpmdMemSizeX7 : + (level >= 5 ? kPpmdMemSizeX5 : + kPpmdMemSizeX1))); + + UInt32 order = + (level >= 9 ? kPpmdOrderX9 : + (level >= 7 ? kPpmdOrderX7 : + (level >= 5 ? kPpmdOrderX5 : + kPpmdOrderX1))); + + SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); + } +} + +static void SplitParams(const UString &srcString, UStringVector &subStrings) +{ + subStrings.Clear(); + UString name; + int len = srcString.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L':') + { + subStrings.Add(name); + name.Empty(); + } + else + name += c; + } + subStrings.Add(name); +} + +static void SplitParam(const UString ¶m, UString &name, UString &value) +{ + int eqPos = param.Find(L'='); + if (eqPos >= 0) + { + name = param.Left(eqPos); + value = param.Mid(eqPos + 1); + return; + } + for(int i = 0; i < param.Length(); i++) + { + wchar_t c = param[i]; + if (c >= L'0' && c <= L'9') + { + name = param.Left(i); + value = param.Mid(i); + return; + } + } + name = param; +} + +HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) +{ + CProp prop; + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) + { + UInt32 dicSize; + RINOK(ParsePropDictionaryValue(value, dicSize)); + prop.Value = dicSize; + } + else + { + NCOM::CPropVariant propValue; + + if (nameToPropID.VarType == VT_BSTR) + propValue = value; + else if (nameToPropID.VarType == VT_BOOL) + { + bool res; + if (!StringToBool(value, res)) + return E_INVALIDARG; + propValue = res; + } + else + { + UInt32 number; + if (ParseStringToUInt32(value, number) == value.Length()) + propValue = number; + else + propValue = value; + } + + if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + oneMethodInfo.Props.Add(prop); + return S_OK; +} + +HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) +{ + UStringVector params; + SplitParams(srcString, params); + if (params.Size() > 0) + oneMethodInfo.MethodName = params[0]; + for (int i = 1; i < params.Size(); i++) + { + const UString ¶m = params[i]; + UString name, value; + SplitParam(param, name, value); + RINOK(SetParam(oneMethodInfo, name, value)); + } + return S_OK; +} + +HRESULT COutHandler::SetSolidSettings(const UString &s) +{ + UString s2 = s; + s2.MakeUpper(); + for (int i = 0; i < s2.Length();) + { + const wchar_t *start = ((const wchar_t *)s2) + i; + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(start, &end); + if (start == end) + { + if (s2[i++] != 'E') + return E_INVALIDARG; + _solidExtension = true; + continue; + } + i += (int)(end - start); + if (i == s2.Length()) + return E_INVALIDARG; + wchar_t c = s2[i++]; + switch(c) + { + case 'F': + if (v < 1) + v = 1; + _numSolidFiles = v; + break; + case 'B': + _numSolidBytes = v; + _numSolidBytesDefined = true; + break; + case 'K': + _numSolidBytes = (v << 10); + _numSolidBytesDefined = true; + break; + case 'M': + _numSolidBytes = (v << 20); + _numSolidBytesDefined = true; + break; + case 'G': + _numSolidBytes = (v << 30); + _numSolidBytesDefined = true; + break; + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) +{ + bool isSolid; + switch(value.vt) + { + case VT_EMPTY: + isSolid = true; + break; + case VT_BOOL: + isSolid = (value.boolVal != VARIANT_FALSE); + break; + case VT_BSTR: + if (StringToBool(value.bstrVal, isSolid)) + break; + return SetSolidSettings(value.bstrVal); + default: + return E_INVALIDARG; + } + if (isSolid) + InitSolid(); + else + _numSolidFiles = 1; + return S_OK; +} + +void COutHandler::Init() +{ + _removeSfxBlock = false; + _compressHeaders = true; + _encryptHeadersSpecified = false; + _encryptHeaders = false; + + WriteCTime = false; + WriteATime = false; + WriteMTime = true; + + #ifndef _7ZIP_ST + _numThreads = NSystem::GetNumberOfProcessors(); + #endif + + _level = 5; + _autoFilter = true; + _volumeMode = false; + _crcSize = 4; + InitSolid(); +} + +void COutHandler::BeforeSetProperty() +{ + Init(); + #ifndef _7ZIP_ST + numProcessors = NSystem::GetNumberOfProcessors(); + #endif + + mainDicSize = 0xFFFFFFFF; + mainDicMethodIndex = 0xFFFFFFFF; + minNumber = 0; + _crcSize = 4; +} + +HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == 'X') + { + name.Delete(0); + _level = 9; + return ParsePropValue(name, value, _level); + } + + if (name[0] == L'S') + { + name.Delete(0); + if (name.IsEmpty()) + return SetSolidSettings(value); + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + return SetSolidSettings(name); + } + + if (name == L"CRC") + { + _crcSize = 4; + name.Delete(0, 3); + return ParsePropValue(name, value, _crcSize); + } + + UInt32 number; + int index = ParseStringToUInt32(name, number); + UString realName = name.Mid(index); + if (index == 0) + { + if(name.Left(2).CompareNoCase(L"MT") == 0) + { + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + #endif + return S_OK; + } + if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); + if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); + if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); + if (name.CompareNoCase(L"HCF") == 0) + { + bool compressHeadersFull = true; + RINOK(SetBoolProperty(compressHeadersFull, value)); + if (!compressHeadersFull) + return E_INVALIDARG; + return S_OK; + } + if (name.CompareNoCase(L"HE") == 0) + { + RINOK(SetBoolProperty(_encryptHeaders, value)); + _encryptHeadersSpecified = true; + return S_OK; + } + if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); + if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); + if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); + if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); + number = 0; + } + if (number > 10000) + return E_FAIL; + if (number < minNumber) + return E_INVALIDARG; + number -= minNumber; + for(int j = _methods.Size(); j <= (int)number; j++) + { + COneMethodInfo oneMethodInfo; + _methods.Add(oneMethodInfo); + } + + COneMethodInfo &oneMethodInfo = _methods[number]; + + if (realName.Length() == 0) + { + if (value.vt != VT_BSTR) + return E_INVALIDARG; + + RINOK(SetParams(oneMethodInfo, value.bstrVal)); + } + else + { + int index = FindPropIdStart(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + CProp prop; + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) + { + UInt32 dicSize; + RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize)); + prop.Value = dicSize; + if (number <= mainDicMethodIndex) + mainDicSize = dicSize; + } + else + { + int index = FindPropIdExact(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + prop.Id = nameToPropID.PropID; + if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + oneMethodInfo.Props.Add(prop); + } + return S_OK; +} + +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h new file mode 100644 index 000000000..72ea40321 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h @@ -0,0 +1,87 @@ +// HandlerOut.h + +#ifndef __HANDLER_OUT_H +#define __HANDLER_OUT_H + +#include "../../../Common/MyString.h" +#include "../../Common/MethodProps.h" + +namespace NArchive { + +struct COneMethodInfo +{ + CObjectVector<CProp> Props; + UString MethodName; + + bool IsLzma() const; +}; + +class COutHandler +{ +public: + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); + + HRESULT SetSolidSettings(const UString &s); + HRESULT SetSolidSettings(const PROPVARIANT &value); + + #ifndef _7ZIP_ST + UInt32 _numThreads; + #endif + + UInt32 _crcSize; + + CObjectVector<COneMethodInfo> _methods; + bool _removeSfxBlock; + + UInt64 _numSolidFiles; + UInt64 _numSolidBytes; + bool _numSolidBytesDefined; + bool _solidExtension; + + bool _compressHeaders; + bool _encryptHeadersSpecified; + bool _encryptHeaders; + + bool WriteCTime; + bool WriteATime; + bool WriteMTime; + + bool _autoFilter; + UInt32 _level; + + bool _volumeMode; + + HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); + HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); + + void SetCompressionMethod2(COneMethodInfo &oneMethodInfo + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ); + + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } + void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } + void InitSolid() + { + InitSolidFiles(); + InitSolidSize(); + _solidExtension = false; + _numSolidBytesDefined = false; + } + + void Init(); + + COutHandler() { Init(); } + + void BeforeSetProperty(); + + UInt32 minNumber; + UInt32 numProcessors; + UInt32 mainDicSize; + UInt32 mainDicMethodIndex; +}; + +} + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp new file mode 100644 index 000000000..569a56f3b --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp @@ -0,0 +1,42 @@ +// InStreamWithCRC.cpp + +#include "StdAfx.h" + +#include "InStreamWithCRC.h" + +STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + _size += realProcessedSize; + if (size > 0 && realProcessedSize == 0) + _wasFinished = true; + _crc = CrcUpdate(_crc, data, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + /* + if (size > 0 && realProcessedSize == 0) + _wasFinished = true; + */ + _size += realProcessedSize; + _crc = CrcUpdate(_crc, data, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (seekOrigin != STREAM_SEEK_SET || offset != 0) + return E_FAIL; + _size = 0; + _crc = CRC_INIT_VAL; + return _stream->Seek(offset, seekOrigin, newPosition); +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h new file mode 100644 index 000000000..31b761e45 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h @@ -0,0 +1,67 @@ +// InStreamWithCRC.h + +#ifndef __IN_STREAM_WITH_CRC_H +#define __IN_STREAM_WITH_CRC_H + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class CSequentialInStreamWithCRC: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr<ISequentialInStream> _stream; + UInt64 _size; + UInt32 _crc; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + _crc = CRC_INIT_VAL; + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } + UInt64 GetSize() const { return _size; } + bool WasFinished() const { return _wasFinished; } +}; + +class CInStreamWithCRC: + public IInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +private: + CMyComPtr<IInStream> _stream; + UInt64 _size; + UInt32 _crc; + // bool _wasFinished; +public: + void SetStream(IInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + // _wasFinished = false; + _crc = CRC_INIT_VAL; + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } + UInt64 GetSize() const { return _size; } + // bool WasFinished() const { return _wasFinished; } +}; + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp new file mode 100644 index 000000000..a5e0dc0be --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -0,0 +1,61 @@ +// Archive/Common/ItemNameUtils.cpp + +#include "StdAfx.h" + +#include "../../../../C/Types.h" + +#include "ItemNameUtils.h" + +namespace NArchive { +namespace NItemName { + +static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; +static const wchar_t kDirDelimiter = L'/'; + +UString MakeLegalName(const UString &name) +{ + UString zipName = name; + zipName.Replace(kOSDirDelimiter, kDirDelimiter); + return zipName; +} + +UString GetOSName(const UString &name) +{ + UString newName = name; + newName.Replace(kDirDelimiter, kOSDirDelimiter); + return newName; +} + +UString GetOSName2(const UString &name) +{ + if (name.IsEmpty()) + return UString(); + UString newName = GetOSName(name); + if (newName[newName.Length() - 1] == kOSDirDelimiter) + newName.Delete(newName.Length() - 1); + return newName; +} + +bool HasTailSlash(const AString &name, UINT codePage) +{ + if (name.IsEmpty()) + return false; + LPCSTR prev = + #if defined(_WIN32) && !defined(UNDER_CE) + CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); + #else + (LPCSTR)(name) + (name.Length() - 1); + #endif + return (*prev == '/'); +} + +#ifndef _WIN32 +UString WinNameToOSName(const UString &name) +{ + UString newName = name; + newName.Replace(L'\\', kOSDirDelimiter); + return newName; +} +#endif + +}} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h new file mode 100644 index 000000000..5eafacb12 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -0,0 +1,24 @@ +// Archive/Common/ItemNameUtils.h + +#ifndef __ARCHIVE_ITEMNAMEUTILS_H +#define __ARCHIVE_ITEMNAMEUTILS_H + +#include "../../../Common/MyString.h" + +namespace NArchive { +namespace NItemName { + + UString MakeLegalName(const UString &name); + UString GetOSName(const UString &name); + UString GetOSName2(const UString &name); + bool HasTailSlash(const AString &name, UINT codePage); + + #ifdef _WIN32 + inline UString WinNameToOSName(const UString &name) { return name; } + #else + UString WinNameToOSName(const UString &name); + #endif + +}} + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp new file mode 100644 index 000000000..04d11cafb --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp @@ -0,0 +1,190 @@ +// MultiStream.cpp + +#include "StdAfx.h" + +#include "MultiStream.h" + +STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= _totalLength) + return (_pos == _totalLength) ? S_OK : E_FAIL; + + { + int left = 0, mid = _streamIndex, right = Streams.Size(); + for (;;) + { + CSubStreamInfo &m = Streams[mid]; + if (_pos < m.GlobalOffset) + right = mid; + else if (_pos >= m.GlobalOffset + m.Size) + left = mid + 1; + else + { + _streamIndex = mid; + break; + } + mid = (left + right) / 2; + } + _streamIndex = mid; + } + + CSubStreamInfo &s = Streams[_streamIndex]; + UInt64 localPos = _pos - s.GlobalOffset; + if (localPos != s.LocalPos) + { + RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos)); + } + UInt64 rem = s.Size - localPos; + if (size > rem) + size = (UInt32)rem; + HRESULT result = s.Stream->Read(data, size, &size); + _pos += size; + s.LocalPos += size; + if (processedSize) + *processedSize = size; + return result; +} + +STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _pos = offset; break; + case STREAM_SEEK_CUR: _pos = _pos + offset; break; + case STREAM_SEEK_END: _pos = _totalLength + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition != 0) + *newPosition = _pos; + return S_OK; +} + + +/* +class COutVolumeStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + int _volIndex; + UInt64 _volSize; + UInt64 _curPos; + CMyComPtr<ISequentialOutStream> _volumeStream; + COutArchive _archive; + CCRC _crc; + +public: + MY_UNKNOWN_IMP + + CFileItem _file; + CUpdateOptions _options; + CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; + void Init(IArchiveUpdateCallback2 *volumeCallback, + const UString &name) + { + _file.Name = name; + _file.IsStartPosDefined = true; + _file.StartPos = 0; + + VolumeCallback = volumeCallback; + _volIndex = 0; + _volSize = 0; + } + + HRESULT Flush(); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +HRESULT COutVolumeStream::Flush() +{ + if (_volumeStream) + { + _file.UnPackSize = _curPos; + _file.FileCRC = _crc.GetDigest(); + RINOK(WriteVolumeHeader(_archive, _file, _options)); + _archive.Close(); + _volumeStream.Release(); + _file.StartPos += _file.UnPackSize; + } + return S_OK; +} +*/ + +/* +STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if(processedSize != NULL) + *processedSize = 0; + while(size > 0) + { + if (_streamIndex >= Streams.Size()) + { + CSubStreamInfo subStream; + RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); + RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); + subStream.Pos = 0; + Streams.Add(subStream); + continue; + } + CSubStreamInfo &subStream = Streams[_streamIndex]; + if (_offsetPos >= subStream.Size) + { + _offsetPos -= subStream.Size; + _streamIndex++; + continue; + } + if (_offsetPos != subStream.Pos) + { + CMyComPtr<IOutStream> outStream; + RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); + RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); + subStream.Pos = _offsetPos; + } + + UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); + UInt32 realProcessed; + RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); + data = (void *)((Byte *)data + realProcessed); + size -= realProcessed; + subStream.Pos += realProcessed; + _offsetPos += realProcessed; + _absPos += realProcessed; + if (_absPos > _length) + _length = _absPos; + if(processedSize != NULL) + *processedSize += realProcessed; + if (subStream.Pos == subStream.Size) + { + _streamIndex++; + _offsetPos = 0; + } + if (realProcessed != curSize && realProcessed == 0) + return E_FAIL; + } + return S_OK; +} + +STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if(seekOrigin >= 3) + return STG_E_INVALIDFUNCTION; + switch(seekOrigin) + { + case STREAM_SEEK_SET: + _absPos = offset; + break; + case STREAM_SEEK_CUR: + _absPos += offset; + break; + case STREAM_SEEK_END: + _absPos = _length + offset; + break; + } + _offsetPos = _absPos; + _streamIndex = 0; + return S_OK; +} +*/ diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h new file mode 100644 index 000000000..3fceb7cce --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h @@ -0,0 +1,84 @@ +// MultiStream.h + +#ifndef __MULTI_STREAM_H +#define __MULTI_STREAM_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + +#include "../../IStream.h" + +class CMultiStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _pos; + UInt64 _totalLength; + int _streamIndex; +public: + struct CSubStreamInfo + { + CMyComPtr<IInStream> Stream; + UInt64 Size; + UInt64 GlobalOffset; + UInt64 LocalPos; + }; + CObjectVector<CSubStreamInfo> Streams; + + HRESULT Init() + { + UInt64 total = 0; + for (int i = 0; i < Streams.Size(); i++) + { + CSubStreamInfo &s = Streams[i]; + s.GlobalOffset = total; + total += Streams[i].Size; + RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos)); + } + _totalLength = total; + _pos = 0; + _streamIndex = 0; + return S_OK; + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +/* +class COutMultiStream: + public IOutStream, + public CMyUnknownImp +{ + int _streamIndex; // required stream + UInt64 _offsetPos; // offset from start of _streamIndex index + UInt64 _absPos; + UInt64 _length; + + struct CSubStreamInfo + { + CMyComPtr<ISequentialOutStream> Stream; + UInt64 Size; + UInt64 Pos; + }; + CObjectVector<CSubStreamInfo> Streams; +public: + CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; + void Init() + { + _streamIndex = 0; + _offsetPos = 0; + _absPos = 0; + _length = 0; + } + + MY_UNKNOWN_IMP1(IOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; +*/ + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp new file mode 100644 index 000000000..f955c2254 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp @@ -0,0 +1,18 @@ +// OutStreamWithCRC.cpp + +#include "StdAfx.h" + +#include "OutStreamWithCRC.h" + +STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _crc = CrcUpdate(_crc, data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; + return result; +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h new file mode 100644 index 000000000..115b442aa --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -0,0 +1,36 @@ +// OutStreamWithCRC.h + +#ifndef __OUT_STREAM_WITH_CRC_H +#define __OUT_STREAM_WITH_CRC_H + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class COutStreamWithCRC: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; + UInt32 _crc; + bool _calculate; +public: + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(bool calculate = true) + { + _size = 0; + _calculate = calculate; + _crc = CRC_INIT_VAL; + } + void InitCRC() { _crc = CRC_INIT_VAL; } + UInt64 GetSize() const { return _size; } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } +}; + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp new file mode 100644 index 000000000..0526c1b1d --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -0,0 +1,18 @@ +// OutStreamWithSha1.cpp + +#include "StdAfx.h" + +#include "OutStreamWithSha1.h" + +STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _sha.Update((const Byte *)data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; + return result; +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithSha1.h new file mode 100644 index 000000000..3bbfbbe19 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -0,0 +1,36 @@ +// OutStreamWithSha1.h + +#ifndef __OUT_STREAM_WITH_SHA1_H +#define __OUT_STREAM_WITH_SHA1_H + +#include "../../Crypto/Sha1.h" + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class COutStreamWithSha1: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; + NCrypto::NSha1::CContext _sha; + bool _calculate; +public: + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(bool calculate = true) + { + _size = 0; + _calculate = calculate; + _sha.Init(); + } + void InitSha1() { _sha.Init(); } + UInt64 GetSize() const { return _size; } + void Final(Byte *digest) { _sha.Final(digest); } +}; + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.cpp new file mode 100644 index 000000000..5cd849e29 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.cpp @@ -0,0 +1,177 @@ +// ParseProperties.cpp + +#include "StdAfx.h" + +#include "ParseProperties.h" + +#include "Common/StringToInt.h" +#include "Common/MyCom.h" + +HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + if (prop.vt == VT_UI4) + { + if (!name.IsEmpty()) + return E_INVALIDARG; + resValue = prop.ulVal; + } + else if (prop.vt == VT_EMPTY) + { + if(!name.IsEmpty()) + { + const wchar_t *start = name; + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(start, &end); + if (end - start != name.Length()) + return E_INVALIDARG; + resValue = (UInt32)v; + } + } + else + return E_INVALIDARG; + return S_OK; +} + +static const int kLogarithmicSizeLimit = 32; +static const wchar_t kByteSymbol = L'B'; +static const wchar_t kKiloByteSymbol = L'K'; +static const wchar_t kMegaByteSymbol = L'M'; + +HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) +{ + UString srcString = srcStringSpec; + srcString.MakeUpper(); + + const wchar_t *start = srcString; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(start, &end); + int numDigits = (int)(end - start); + if (numDigits == 0 || srcString.Length() > numDigits + 1) + return E_INVALIDARG; + if (srcString.Length() == numDigits) + { + if (number >= kLogarithmicSizeLimit) + return E_INVALIDARG; + dicSize = (UInt32)1 << (int)number; + return S_OK; + } + switch (srcString[numDigits]) + { + case kByteSymbol: + if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) + return E_INVALIDARG; + dicSize = (UInt32)number; + break; + case kKiloByteSymbol: + if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) + return E_INVALIDARG; + dicSize = (UInt32)(number << 10); + break; + case kMegaByteSymbol: + if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) + return E_INVALIDARG; + dicSize = (UInt32)(number << 20); + break; + default: + return E_INVALIDARG; + } + return S_OK; +} + +HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + if (name.IsEmpty()) + { + if (prop.vt == VT_UI4) + { + UInt32 logDicSize = prop.ulVal; + if (logDicSize >= 32) + return E_INVALIDARG; + resValue = (UInt32)1 << logDicSize; + return S_OK; + } + if (prop.vt == VT_BSTR) + return ParsePropDictionaryValue(prop.bstrVal, resValue); + return E_INVALIDARG; + } + return ParsePropDictionaryValue(name, resValue); +} + +bool StringToBool(const UString &s, bool &res) +{ + if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) + { + res = true; + return true; + } + if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) + { + res = false; + return true; + } + return false; +} + +HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) +{ + switch(value.vt) + { + case VT_EMPTY: + dest = true; + return S_OK; + case VT_BOOL: + dest = (value.boolVal != VARIANT_FALSE); + return S_OK; + /* + case VT_UI4: + dest = (value.ulVal != 0); + break; + */ + case VT_BSTR: + return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; + } + return E_INVALIDARG; +} + +int ParseStringToUInt32(const UString &srcString, UInt32 &number) +{ + const wchar_t *start = srcString; + const wchar_t *end; + UInt64 number64 = ConvertStringToUInt64(start, &end); + if (number64 > 0xFFFFFFFF) + { + number = 0; + return 0; + } + number = (UInt32)number64; + return (int)(end - start); +} + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) +{ + if (name.IsEmpty()) + { + switch(prop.vt) + { + case VT_UI4: + numThreads = prop.ulVal; + break; + default: + { + bool val; + RINOK(SetBoolProperty(val, prop)); + numThreads = (val ? defaultNumThreads : 1); + break; + } + } + } + else + { + UInt32 number; + int index = ParseStringToUInt32(name, number); + if (index != name.Length()) + return E_INVALIDARG; + numThreads = number; + } + return S_OK; +} diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h new file mode 100644 index 000000000..6f80f6344 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h @@ -0,0 +1,18 @@ +// ParseProperties.h + +#ifndef __PARSEPROPERTIES_H +#define __PARSEPROPERTIES_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); +HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); +HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); + +bool StringToBool(const UString &s, bool &res); +HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); +int ParseStringToUInt32(const UString &srcString, UInt32 &number); +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); + +#endif diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h b/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h new file mode 100644 index 000000000..2e4be10b2 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif |