summaryrefslogtreecommitdiffstats
path: root/CPP/7zip/Archive/Common
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Common')
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2.cpp121
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2.h174
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2MT.cpp240
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2MT.h80
-rwxr-xr-xCPP/7zip/Archive/Common/CrossThreadProgress.cpp15
-rwxr-xr-xCPP/7zip/Archive/Common/CrossThreadProgress.h37
-rwxr-xr-xCPP/7zip/Archive/Common/DummyOutStream.cpp22
-rwxr-xr-xCPP/7zip/Archive/Common/DummyOutStream.h24
-rwxr-xr-xCPP/7zip/Archive/Common/HandlerOut.cpp623
-rwxr-xr-xCPP/7zip/Archive/Common/HandlerOut.h87
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.cpp42
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.h67
-rwxr-xr-xCPP/7zip/Archive/Common/ItemNameUtils.cpp61
-rwxr-xr-xCPP/7zip/Archive/Common/ItemNameUtils.h24
-rwxr-xr-xCPP/7zip/Archive/Common/MultiStream.cpp190
-rwxr-xr-xCPP/7zip/Archive/Common/MultiStream.h84
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.cpp18
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.h36
-rwxr-xr-xCPP/7zip/Archive/Common/ParseProperties.cpp177
-rwxr-xr-xCPP/7zip/Archive/Common/ParseProperties.h18
-rwxr-xr-xCPP/7zip/Archive/Common/StdAfx.h9
21 files changed, 2149 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
new file mode 100755
index 0000000..417e8a7
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
new file mode 100755
index 0000000..b1893b2
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
new file mode 100755
index 0000000..3047b13
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
new file mode 100755
index 0000000..acecc39
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
new file mode 100755
index 0000000..62d05af
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
new file mode 100755
index 0000000..d414958
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp
new file mode 100755
index 0000000..237e01e
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h
new file mode 100755
index 0000000..c993bb3
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
new file mode 100755
index 0000000..c2254a7
--- /dev/null
+++ b/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 &param, 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 &param = 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/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
new file mode 100755
index 0000000..c4ccf37
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
new file mode 100755
index 0000000..6338d0a
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
new file mode 100755
index 0000000..1a4b2c9
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
new file mode 100755
index 0000000..287ddce
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
new file mode 100755
index 0000000..8b91d1c
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp
new file mode 100755
index 0000000..83b3da1
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h
new file mode 100755
index 0000000..74ec6ad
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
new file mode 100755
index 0000000..e0d3894
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
new file mode 100755
index 0000000..d9eb646
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
new file mode 100755
index 0000000..5550a23
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
new file mode 100755
index 0000000..c64fc1e
--- /dev/null
+++ b/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/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/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