diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2007-01-20 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:49 +0300 |
commit | d9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch) | |
tree | c722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/Common | |
parent | 804edc5756fede54dbb1aefda6d39d306111938d (diff) |
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/Common')
27 files changed, 2505 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Common/CodecsPath.cpp b/CPP/7zip/Archive/Common/CodecsPath.cpp new file mode 100755 index 00000000..7ee89875 --- /dev/null +++ b/CPP/7zip/Archive/Common/CodecsPath.cpp @@ -0,0 +1,34 @@ +// CodecsPath.cpp + +#include "StdAfx.h" +#include "../../../Common/String.h" + +extern HINSTANCE g_hInstance; + +static CSysString GetLibraryPath() +{ + TCHAR fullPath[MAX_PATH + 1]; + ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); + return fullPath; +} + +static CSysString GetLibraryFolderPrefix() +{ + CSysString path = GetLibraryPath(); + int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); + return path.Left(pos + 1); +} + +CSysString GetBaseFolderPrefix() +{ + CSysString libPrefix = GetLibraryFolderPrefix(); + CSysString temp = libPrefix; + temp.Delete(temp.Length() - 1); + int pos = temp.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); + return temp.Left(pos + 1); +} + +CSysString GetCodecsFolderPrefix() +{ + return GetBaseFolderPrefix() + (CSysString)(TEXT("Codecs")) + (CSysString)(TEXT(STRING_PATH_SEPARATOR)); +} diff --git a/CPP/7zip/Archive/Common/CodecsPath.h b/CPP/7zip/Archive/Common/CodecsPath.h new file mode 100755 index 00000000..11145a03 --- /dev/null +++ b/CPP/7zip/Archive/Common/CodecsPath.h @@ -0,0 +1,12 @@ +// CodecsPath.h + +#ifndef __CODECSPATH_H +#define __CODECSPATH_H + +#include "../../../Common/String.h" + +CSysString GetBaseFolderPrefix(); +CSysString GetCodecsFolderPrefix(); + +#endif + diff --git a/CPP/7zip/Archive/Common/CoderLoader.cpp b/CPP/7zip/Archive/Common/CoderLoader.cpp new file mode 100755 index 00000000..bf54f6e0 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderLoader.cpp @@ -0,0 +1,31 @@ +// CoderLoader.cpp + +#include "StdAfx.h" + +#include "CoderLoader.h" +#include "FilterCoder.h" + +HRESULT CCoderLibrary::CreateCoderSpec(REFGUID clsID, ICompressCoder **coder) +{ + HRESULT result = CreateObject(clsID, IID_ICompressCoder, (void **)coder); + if (result == S_OK || result != E_NOINTERFACE) + return result; + CMyComPtr<ICompressFilter> filter; + RINOK(CreateObject(clsID, IID_ICompressFilter, (void **)&filter)); + CFilterCoder *filterCoderSpec = new CFilterCoder; + CMyComPtr<ICompressCoder> filterCoder = filterCoderSpec; + filterCoderSpec->Filter = filter; + *coder = filterCoder.Detach(); + return S_OK; +} + + +HRESULT CCoderLibrary::LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder) +{ + CCoderLibrary libTemp; + if (!libTemp.Load(filePath)) + return GetLastError(); + RINOK(libTemp.CreateCoderSpec(clsID, coder)); + Attach(libTemp.Detach()); + return S_OK; +} diff --git a/CPP/7zip/Archive/Common/CoderLoader.h b/CPP/7zip/Archive/Common/CoderLoader.h new file mode 100755 index 00000000..02322d8c --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderLoader.h @@ -0,0 +1,147 @@ +// CoderLoader.h + +#ifndef __CODERLOADER_H +#define __CODERLOADER_H + +#include "../../../Common/String.h" +#include "../../../Common/MyCom.h" +#include "../../../Windows/DLL.h" +#include "../../ICoder.h" + +typedef UInt32 (WINAPI * CreateObjectPointer)( + const GUID *clsID, + const GUID *interfaceID, + void **outObject); + +class CCoderLibrary: public NWindows::NDLL::CLibrary +{ +public: + HRESULT CreateObject(REFGUID clsID, REFGUID iid, void **obj) + { + CreateObjectPointer createObject = (CreateObjectPointer) + GetProcAddress("CreateObject"); + if (createObject == NULL) + return GetLastError(); + return createObject(&clsID, &iid, obj); + } + + HRESULT CreateFilter(REFGUID clsID, ICompressFilter **filter) + { + return CreateObject(clsID, IID_ICompressFilter, (void **)filter); + } + + HRESULT CreateCoder(REFGUID clsID, ICompressCoder **coder) + { + return CreateObject(clsID, IID_ICompressCoder, (void **)coder); + } + + HRESULT CreateCoderSpec(REFGUID clsID, ICompressCoder **coder); + + HRESULT LoadAndCreateFilter(LPCTSTR filePath, REFGUID clsID, ICompressFilter **filter) + { + CCoderLibrary libTemp; + if (!libTemp.Load(filePath)) + return GetLastError(); + RINOK(libTemp.CreateFilter(clsID, filter)); + Attach(libTemp.Detach()); + return S_OK; + } + + + HRESULT LoadAndCreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder) + { + CCoderLibrary libTemp; + if (!libTemp.Load(filePath)) + return GetLastError(); + RINOK(libTemp.CreateCoder(clsID, coder)); + Attach(libTemp.Detach()); + return S_OK; + } + + HRESULT LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder); + HRESULT CreateCoder2(REFGUID clsID, ICompressCoder2 **coder) + { + CreateObjectPointer createObject = (CreateObjectPointer) + GetProcAddress("CreateObject"); + if (createObject == NULL) + return GetLastError(); + return createObject(&clsID, &IID_ICompressCoder2, (void **)coder); + } + HRESULT LoadAndCreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder) + { + CCoderLibrary libTemp; + if (!libTemp.Load(filePath)) + return GetLastError(); + RINOK(libTemp.CreateCoder2(clsID, coder)); + Attach(libTemp.Detach()); + return S_OK; + } +}; + + +class CCoderLibraries +{ + struct CPathToLibraryPair + { + CSysString Path; + CCoderLibrary Libary; + }; + CObjectVector<CPathToLibraryPair> Pairs; +public: + int FindPath(LPCTSTR filePath) + { + for (int i = 0; i < Pairs.Size(); i++) + if (Pairs[i].Path.CompareNoCase(filePath) == 0) + return i; + return -1; + } + + HRESULT CreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder) + { + int index = FindPath(filePath); + if (index < 0) + { + CPathToLibraryPair pair; + RINOK(pair.Libary.LoadAndCreateCoder(filePath, clsID, coder)); + pair.Path = filePath; + Pairs.Add(pair); + pair.Libary.Detach(); + return S_OK; + } + return Pairs[index].Libary.CreateCoder(clsID, coder); + } + + HRESULT CreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder) + { + int index = FindPath(filePath); + if (index < 0) + { + CPathToLibraryPair pair; + RINOK(pair.Libary.LoadAndCreateCoderSpec(filePath, clsID, coder)); + pair.Path = filePath; + Pairs.Add(pair); + pair.Libary.Detach(); + return S_OK; + } + return Pairs[index].Libary.CreateCoderSpec(clsID, coder); + } + + HRESULT CreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder) + { + int index = FindPath(filePath); + if (index < 0) + { + CPathToLibraryPair pair; + RINOK(pair.Libary.LoadAndCreateCoder2(filePath, clsID, coder)); + pair.Path = filePath; + Pairs.Add(pair); + pair.Libary.Detach(); + return S_OK; + } + return Pairs[index].Libary.CreateCoder2(clsID, coder); + } +}; + + +#endif + diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp new file mode 100755 index 00000000..8f46e985 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -0,0 +1,121 @@ +// CoderMixer2.cpp + +#include "StdAfx.h" + +#include "CoderMixer2.h" + +namespace NCoderMixer2 { + +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]]); +} + +CCoderInfo::CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams): + NumInStreams(numInStreams), + NumOutStreams(numOutStreams) +{ + InSizes.Reserve(NumInStreams); + InSizePointers.Reserve(NumInStreams); + OutSizePointers.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 CCoderInfo::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 00000000..78a3f280 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -0,0 +1,168 @@ +// CoderMixer2.h + +#ifndef __CODER_MIXER2_H +#define __CODER_MIXER2_H + +#include "../../../Common/Vector.h" +#include "../../../Common/Types.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer2 { + +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; + NCoderMixer2::CBindInfo _srcBindInfo; + CRecordVector<UInt32> _srcInToDestOutMap; + CRecordVector<UInt32> _srcOutToDestInMap; + CRecordVector<UInt32> _destInToSrcOutMap; +public: + UInt32 NumSrcInStreams; + CRecordVector<UInt32> DestOutToSrcInMap; + + CBindReverseConverter(const NCoderMixer2::CBindInfo &srcBindInfo); + void CreateReverseBindInfo(NCoderMixer2::CBindInfo &destBindInfo); +}; + +struct CCoderInfo +{ + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ICompressCoder2> Coder2; + UInt32 NumInStreams; + UInt32 NumOutStreams; + + CRecordVector<UInt64> InSizes; + CRecordVector<UInt64> OutSizes; + CRecordVector<const UInt64 *> InSizePointers; + CRecordVector<const UInt64 *> OutSizePointers; + + CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams); + void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); +}; + +class CCoderMixer2 +{ +public: + virtual void 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 00000000..9d7944b1 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -0,0 +1,359 @@ +// CoderMixer2MT.cpp + +#include "StdAfx.h" + +#include "CoderMixer2MT.h" +#include "CrossThreadProgress.h" + +using namespace NWindows; +using namespace NSynchronization; + +namespace NCoderMixer2 { + +CThreadCoderInfo::CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams): + ExitEvent(NULL), + CompressEvent(NULL), + CompressionCompletedEvent(NULL), + CCoderInfo(numInStreams, numOutStreams) +{ + InStreams.Reserve(NumInStreams); + InStreamPointers.Reserve(NumInStreams); + OutStreams.Reserve(NumOutStreams); + OutStreamPointers.Reserve(NumOutStreams); +} + +void CThreadCoderInfo::CreateEvents() +{ + CompressEvent = new CAutoResetEvent(false); + CompressionCompletedEvent = new CAutoResetEvent(false); +} + +CThreadCoderInfo::~CThreadCoderInfo() +{ + if (CompressEvent != NULL) + delete CompressEvent; + if (CompressionCompletedEvent != NULL) + delete CompressionCompletedEvent; +} + +class CCoderInfoFlusher2 +{ + CThreadCoderInfo *m_CoderInfo; +public: + CCoderInfoFlusher2(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {} + ~CCoderInfoFlusher2() + { + int i; + for (i = 0; i < m_CoderInfo->InStreams.Size(); i++) + m_CoderInfo->InStreams[i].Release(); + for (i = 0; i < m_CoderInfo->OutStreams.Size(); i++) + m_CoderInfo->OutStreams[i].Release(); + m_CoderInfo->CompressionCompletedEvent->Set(); + } +}; + +bool CThreadCoderInfo::WaitAndCode() +{ + HANDLE events[2] = { ExitEvent, *CompressEvent }; + DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); + if (waitResult == WAIT_OBJECT_0 + 0) + return false; + + { + InStreamPointers.Clear(); + OutStreamPointers.Clear(); + UInt32 i; + for (i = 0; i < NumInStreams; i++) + { + if (InSizePointers[i] != NULL) + InSizePointers[i] = &InSizes[i]; + InStreamPointers.Add(InStreams[i]); + } + for (i = 0; i < NumOutStreams; i++) + { + if (OutSizePointers[i] != NULL) + OutSizePointers[i] = &OutSizes[i]; + OutStreamPointers.Add(OutStreams[i]); + } + CCoderInfoFlusher2 coderInfoFlusher(this); + 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); + } + return true; +} + +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 CThreadCoderInfo::SetCoderInfo(const UInt64 **inSizes, + const UInt64 **outSizes, ICompressProgressInfo *progress) +{ + Progress = progress; + SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); + SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); +} + +static DWORD WINAPI CoderThread(void *threadCoderInfo) +{ + for (;;) + { + if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode()) + return 0; + } +} + +////////////////////////////////////// +// CCoderMixer2MT + +static DWORD WINAPI MainCoderThread(void *threadCoderInfo) +{ + for (;;) + { + if (!((CCoderMixer2MT *)threadCoderInfo)->MyCode()) + return 0; + } +} + +CCoderMixer2MT::CCoderMixer2MT() +{ + if (!_mainThread.Create(MainCoderThread, this)) + throw 271825; +} + +CCoderMixer2MT::~CCoderMixer2MT() +{ + _exitEvent.Set(); + _mainThread.Wait(); + for(int i = 0; i < _threads.Size(); i++) + { + _threads[i].Wait(); + _threads[i].Close(); + } +} + +void CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) +{ + _bindInfo = bindInfo; + _streamBinders.Clear(); + for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) + { + _streamBinders.Add(CStreamBinder()); + _streamBinders.Back().CreateEvents(); + } +} + +void CCoderMixer2MT::AddCoderCommon() +{ + int index = _coderInfoVector.Size(); + const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index]; + + CThreadCoderInfo threadCoderInfo(CoderStreamsInfo.NumInStreams, + CoderStreamsInfo.NumOutStreams); + _coderInfoVector.Add(threadCoderInfo); + _coderInfoVector.Back().CreateEvents(); + _coderInfoVector.Back().ExitEvent = _exitEvent; + _compressingCompletedEvents.Add(*_coderInfoVector.Back().CompressionCompletedEvent); + + NWindows::CThread newThread; + _threads.Add(newThread); + if (!_threads.Back().Create(CoderThread, &_coderInfoVector.Back())) + throw 271824; +} + +void CCoderMixer2MT::AddCoder(ICompressCoder *coder) +{ + AddCoderCommon(); + _coderInfoVector.Back().Coder = coder; +} + +void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) +{ + AddCoderCommon(); + _coderInfoVector.Back().Coder2 = coder; +} + +/* +void CCoderMixer2MT::FinishAddingCoders() +{ + for(int i = 0; i < _coderInfoVector.Size(); i++) + { + DWORD id; + HANDLE newThread = ::CreateThread(NULL, 0, CoderThread, + &_coderInfoVector[i], 0, &id); + if (newThread == 0) + throw 271824; + _threads.Add(newThread); + } +} +*/ + +void CCoderMixer2MT::ReInit() +{ + for(int i = 0; i < _streamBinders.Size(); i++) + _streamBinders[i].ReInit(); +} + + +STDMETHODIMP CCoderMixer2MT::Init(ISequentialInStream **inStreams, + ISequentialOutStream **outStreams) +{ + if (_coderInfoVector.Size() != _bindInfo.Coders.Size()) + throw 0; + int i; + for(i = 0; i < _coderInfoVector.Size(); i++) + { + CThreadCoderInfo &coderInfo = _coderInfoVector[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( + &_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex], + &_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex]); + } + + for(i = 0; i < _bindInfo.InStreams.Size(); i++) + { + UInt32 inCoderIndex, inCoderStreamIndex; + _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); + _coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; + } + + for(i = 0; i < _bindInfo.OutStreams.Size(); i++) + { + UInt32 outCoderIndex, outCoderStreamIndex; + _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); + _coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; + } + return S_OK; +} + + +bool CCoderMixer2MT::MyCode() +{ + HANDLE events[2] = { _exitEvent, _startCompressingEvent }; + DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); + if (waitResult == WAIT_OBJECT_0 + 0) + return false; + + for(int i = 0; i < _coderInfoVector.Size(); i++) + _coderInfoVector[i].CompressEvent->Set(); + /* DWORD result = */ ::WaitForMultipleObjects(_compressingCompletedEvents.Size(), + &_compressingCompletedEvents.Front(), TRUE, INFINITE); + + _compressingFinishedEvent.Set(); + + return true; +} + + +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); + + _compressingFinishedEvent.Reset(); // ? + + CCrossThreadProgress *progressSpec = new CCrossThreadProgress; + CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec; + progressSpec->Init(); + _coderInfoVector[_progressCoderIndex].Progress = crossProgress; + + _startCompressingEvent.Set(); + + + for (;;) + { + HANDLE events[2] = {_compressingFinishedEvent, progressSpec->ProgressEvent }; + DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); + if (waitResult == WAIT_OBJECT_0 + 0) + break; + if (progress != NULL) + progressSpec->Result = progress->SetRatioInfo(progressSpec->InSize, + progressSpec->OutSize); + else + progressSpec->Result = S_OK; + progressSpec->WaitEvent.Set(); + } + + int i; + for(i = 0; i < _coderInfoVector.Size(); i++) + { + HRESULT result = _coderInfoVector[i].Result; + if (result == S_FALSE) + return result; + } + for(i = 0; i < _coderInfoVector.Size(); i++) + { + HRESULT result = _coderInfoVector[i].Result; + if (result != S_OK && result != E_FAIL) + return result; + } + for(i = 0; i < _coderInfoVector.Size(); i++) + { + HRESULT result = _coderInfoVector[i].Result; + if (result != S_OK) + return result; + } + return S_OK; +} + +UInt64 CCoderMixer2MT::GetWriteProcessedSize(UInt32 binderIndex) const +{ + return _streamBinders[binderIndex].ProcessedSize; +} + +} diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h new file mode 100755 index 00000000..78d752de --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -0,0 +1,121 @@ +// CoderMixer2MT.h + +#ifndef __CODER_MIXER2_MT_H +#define __CODER_MIXER2_MT_H + +#include "CoderMixer2.h" +#include "../../../Common/MyCom.h" +#include "../../../Windows/Thread.h" +#include "../../Common/StreamBinder.h" + +namespace NCoderMixer2 { + +// CreateEvents(); +// { +// SetCoderInfo() +// Init Streams +// set CompressEvent() +// wait CompressionCompletedEvent +// } + +struct CThreadCoderInfo: public CCoderInfo +{ + NWindows::NSynchronization::CAutoResetEvent *CompressEvent; + HANDLE ExitEvent; + NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent; + + CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; + CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; + CRecordVector<ISequentialInStream *> InStreamPointers; + CRecordVector<ISequentialOutStream *> OutStreamPointers; + + CMyComPtr<ICompressProgressInfo> Progress; // CMyComPtr + HRESULT Result; + + CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams); + void SetCoderInfo(const UInt64 **inSizes, + const UInt64 **outSizes, ICompressProgressInfo *progress); + ~CThreadCoderInfo(); + bool WaitAndCode(); + void CreateEvents(); +}; + + +// SetBindInfo() +// for each coder +// { +// AddCoder[2]() +// } +// +// for each file +// { +// ReInit() +// for each coder +// { +// SetCoderInfo +// } +// SetProgressIndex(UInt32 coderIndex); +// Code +// } + + +class CCoderMixer2MT: + public ICompressCoder2, + public CCoderMixer2, + public CMyUnknownImp +{ + MY_UNKNOWN_IMP + +public: + STDMETHOD(Init)(ISequentialInStream **inStreams, + ISequentialOutStream **outStreams); + + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + + + CCoderMixer2MT(); + ~CCoderMixer2MT(); + void AddCoderCommon(); + void AddCoder(ICompressCoder *coder); + void AddCoder2(ICompressCoder2 *coder); + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) + { _coderInfoVector[coderIndex].SetCoderInfo(inSizes, outSizes, NULL); } + void SetProgressCoderIndex(UInt32 coderIndex) + { _progressCoderIndex = coderIndex; } + + + UInt64 GetWriteProcessedSize(UInt32 binderIndex) const; + + + bool MyCode(); + +private: + CBindInfo _bindInfo; + CObjectVector<CStreamBinder> _streamBinders; + CObjectVector<CThreadCoderInfo> _coderInfoVector; + CRecordVector<NWindows::CThread> _threads; + NWindows::CThread _mainThread; + + NWindows::NSynchronization::CAutoResetEvent _startCompressingEvent; + CRecordVector<HANDLE> _compressingCompletedEvents; + NWindows::NSynchronization::CAutoResetEvent _compressingFinishedEvent; + + NWindows::NSynchronization::CManualResetEvent _exitEvent; + UInt32 _progressCoderIndex; + +public: + void SetBindInfo(const CBindInfo &bindInfo); + +}; + +} +#endif + diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp new file mode 100755 index 00000000..c01b776d --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -0,0 +1,238 @@ +// CoderMixer2ST.cpp + +#include "StdAfx.h" + +#include "CoderMixer2ST.h" + +namespace NCoderMixer2 { + +CCoderMixer2ST::CCoderMixer2ST() {} + +CCoderMixer2ST::~CCoderMixer2ST(){ } + +void CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo) +{ + _bindInfo = bindInfo; +} + +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/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h new file mode 100755 index 00000000..3144918b --- /dev/null +++ b/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: + void SetBindInfo(const CBindInfo &bindInfo); + +}; + +} +#endif + diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp new file mode 100755 index 00000000..a974b54c --- /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 00000000..5dd339dc --- /dev/null +++ b/CPP/7zip/Archive/Common/CrossThreadProgress.h @@ -0,0 +1,31 @@ +// 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; + 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 00000000..b1d49913 --- /dev/null +++ b/CPP/7zip/Archive/Common/DummyOutStream.cpp @@ -0,0 +1,20 @@ +// DummyOutStream.cpp + +#include "StdAfx.h" + +#include "DummyOutStream.h" + +void CDummyOutStream::Init(ISequentialOutStream *outStream) +{ + m_Stream = outStream; +} + +STDMETHODIMP CDummyOutStream::Write(const void *data, + UInt32 size, UInt32 *processedSize) +{ + if(m_Stream) + return m_Stream->Write(data, size, processedSize); + if(processedSize != NULL) + *processedSize = size; + return S_OK; +} diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h new file mode 100755 index 00000000..51690787 --- /dev/null +++ b/CPP/7zip/Archive/Common/DummyOutStream.h @@ -0,0 +1,23 @@ +// DummyOutStream.h + +#ifndef __DUMMYOUTSTREAM_H +#define __DUMMYOUTSTREAM_H + +#include "../../IStream.h" +#include "Common/MyCom.h" + +class CDummyOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr<ISequentialOutStream> m_Stream; +public: + void Init(ISequentialOutStream *outStream); +}; + +#endif diff --git a/CPP/7zip/Archive/Common/FilterCoder.cpp b/CPP/7zip/Archive/Common/FilterCoder.cpp new file mode 100755 index 00000000..5e104c84 --- /dev/null +++ b/CPP/7zip/Archive/Common/FilterCoder.cpp @@ -0,0 +1,243 @@ +// FilterCoder.cpp + +#include "StdAfx.h" + +#include "FilterCoder.h" +#include "../../../Common/Alloc.h" +#include "../../../Common/Defs.h" +#include "../../Common/StreamUtils.h" + +static const int kBufferSize = 1 << 17; + +CFilterCoder::CFilterCoder() +{ + _buffer = (Byte *)::MidAlloc(kBufferSize); +} + +CFilterCoder::~CFilterCoder() +{ + ::MidFree(_buffer); +} + +HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) +{ + if (_outSizeIsDefined) + { + UInt64 remSize = _outSize - _nowPos64; + if (size > remSize) + size = (UInt32)remSize; + } + UInt32 processedSize = 0; + RINOK(WriteStream(outStream, _buffer, size, &processedSize)); + if (size != processedSize) + return E_FAIL; + _nowPos64 += processedSize; + return S_OK; +} + + +STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + RINOK(Init()); + UInt32 bufferPos = 0; + _outSizeIsDefined = (outSize != 0); + if (_outSizeIsDefined) + _outSize = *outSize; + + while(NeedMore()) + { + UInt32 processedSize; + + // Change it: It can be optimized using ReadPart + RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize)); + + UInt32 endPos = bufferPos + processedSize; + + bufferPos = Filter->Filter(_buffer, endPos); + if (bufferPos > endPos) + { + for (; endPos< bufferPos; endPos++) + _buffer[endPos] = 0; + bufferPos = Filter->Filter(_buffer, endPos); + } + + if (bufferPos == 0) + { + if (endPos > 0) + return WriteWithLimit(outStream, endPos); + return S_OK; + } + RINOK(WriteWithLimit(outStream, bufferPos)); + if (progress != NULL) + { + RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); + } + UInt32 i = 0; + while(bufferPos < endPos) + _buffer[i++] = _buffer[bufferPos++]; + bufferPos = i; + } + return S_OK; +} + +// #ifdef _ST_MODE +STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) +{ + _bufferPos = 0; + _outStream = outStream; + return Init(); +} + +STDMETHODIMP CFilterCoder::ReleaseOutStream() +{ + _outStream.Release(); + return S_OK; +}; + + +STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 processedSizeTotal = 0; + while(size > 0) + { + UInt32 sizeMax = kBufferSize - _bufferPos; + UInt32 sizeTemp = size; + if (sizeTemp > sizeMax) + sizeTemp = sizeMax; + memmove(_buffer + _bufferPos, data, sizeTemp); + size -= sizeTemp; + processedSizeTotal += sizeTemp; + data = (const Byte *)data + sizeTemp; + UInt32 endPos = _bufferPos + sizeTemp; + _bufferPos = Filter->Filter(_buffer, endPos); + if (_bufferPos == 0) + { + _bufferPos = endPos; + break; + } + if (_bufferPos > endPos) + { + if (size != 0) + return E_FAIL; + break; + } + RINOK(WriteWithLimit(_outStream, _bufferPos)); + UInt32 i = 0; + while(_bufferPos < endPos) + _buffer[i++] = _buffer[_bufferPos++]; + _bufferPos = i; + } + if (processedSize != NULL) + *processedSize = processedSizeTotal; + return S_OK; +} + +STDMETHODIMP CFilterCoder::Flush() +{ + if (_bufferPos != 0) + { + UInt32 endPos = Filter->Filter(_buffer, _bufferPos); + if (endPos > _bufferPos) + { + for (; _bufferPos < endPos; _bufferPos++) + _buffer[_bufferPos] = 0; + if (Filter->Filter(_buffer, endPos) != endPos) + return E_FAIL; + } + UInt32 processedSize; + RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize)); + if (_bufferPos != processedSize) + return E_FAIL; + _bufferPos = 0; + } + CMyComPtr<IOutStreamFlush> flush; + _outStream.QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + return flush->Flush(); + return S_OK; +} + + +STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +{ + _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; + _inStream = inStream; + return Init(); +} + +STDMETHODIMP CFilterCoder::ReleaseInStream() +{ + _inStream.Release(); + return S_OK; +}; + +STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 processedSizeTotal = 0; + while(size > 0) + { + if (_convertedPosBegin != _convertedPosEnd) + { + UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); + memmove(data, _buffer + _convertedPosBegin, sizeTemp); + _convertedPosBegin += sizeTemp; + data = (void *)((Byte *)data + sizeTemp); + size -= sizeTemp; + processedSizeTotal += sizeTemp; + break; + } + int i; + for (i = 0; _convertedPosEnd + i < _bufferPos; i++) + _buffer[i] = _buffer[i + _convertedPosEnd]; + _bufferPos = i; + _convertedPosBegin = _convertedPosEnd = 0; + UInt32 processedSizeTemp; + UInt32 size0 = kBufferSize - _bufferPos; + // Optimize it: + RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp)); + _bufferPos = _bufferPos + processedSizeTemp; + _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); + if (_convertedPosEnd == 0) + { + if (_bufferPos == 0) + break; + else + { + _convertedPosEnd = _bufferPos; // check it + continue; + } + } + if (_convertedPosEnd > _bufferPos) + { + for (; _bufferPos < _convertedPosEnd; _bufferPos++) + _buffer[_bufferPos] = 0; + _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); + } + } + if (processedSize != NULL) + *processedSize = processedSizeTotal; + return S_OK; +} + +// #endif // _ST_MODE + +#ifndef _NO_CRYPTO +STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + return _setPassword->CryptoSetPassword(data, size); +} +#endif + +#ifndef EXTRACT_ONLY +STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + return _writeCoderProperties->WriteCoderProperties(outStream); +} +#endif + +STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + return _setDecoderProperties->SetDecoderProperties2(data, size); +} diff --git a/CPP/7zip/Archive/Common/FilterCoder.h b/CPP/7zip/Archive/Common/FilterCoder.h new file mode 100755 index 00000000..45618172 --- /dev/null +++ b/CPP/7zip/Archive/Common/FilterCoder.h @@ -0,0 +1,130 @@ +// FilterCoder.h + +#ifndef __FILTERCODER_H +#define __FILTERCODER_H + +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" +#include "../../IPassword.h" + +#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ +{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ +*outObject = (void *)(i *)this; AddRef(); return S_OK; } + +class CFilterCoder: + public ICompressCoder, + // #ifdef _ST_MODE + public ICompressSetInStream, + public ISequentialInStream, + public ICompressSetOutStream, + public ISequentialOutStream, + public IOutStreamFlush, + // #endif + + #ifndef _NO_CRYPTO + public ICryptoSetPassword, + #endif + #ifndef EXTRACT_ONLY + public ICompressWriteCoderProperties, + #endif + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ +protected: + Byte *_buffer; + // #ifdef _ST_MODE + CMyComPtr<ISequentialInStream> _inStream; + CMyComPtr<ISequentialOutStream> _outStream; + UInt32 _bufferPos; + UInt32 _convertedPosBegin; + UInt32 _convertedPosEnd; + // #endif + bool _outSizeIsDefined; + UInt64 _outSize; + UInt64 _nowPos64; + + HRESULT Init() + { + _nowPos64 = 0; + _outSizeIsDefined = false; + return Filter->Init(); + } + + CMyComPtr<ICryptoSetPassword> _setPassword; + #ifndef EXTRACT_ONLY + CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; + #endif + CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; +public: + CMyComPtr<ICompressFilter> Filter; + + CFilterCoder(); + ~CFilterCoder(); + HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); + bool NeedMore() const + { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } + +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(ICompressCoder) + // #ifdef _ST_MODE + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) + MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) + MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) + // #endif + + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) + #endif + + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) + #endif + + MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + // #ifdef _ST_MODE + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); + STDMETHOD(ReleaseOutStream)(); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Flush)(); + // #endif + + #ifndef _NO_CRYPTO + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + #endif + #ifndef EXTRACT_ONLY + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + #endif + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +// #ifdef _ST_MODE +class CInStreamReleaser +{ +public: + CFilterCoder *FilterCoder; + CInStreamReleaser(): FilterCoder(0) {} + ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } +}; + +class COutStreamReleaser +{ +public: + CFilterCoder *FilterCoder; + COutStreamReleaser(): FilterCoder(0) {} + ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } +}; +// #endif + +#endif diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp new file mode 100755 index 00000000..74dff7e1 --- /dev/null +++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp @@ -0,0 +1,41 @@ +// 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.Update(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.Update(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.Init(); + 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 00000000..770a1437 --- /dev/null +++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h @@ -0,0 +1,65 @@ +// InStreamWithCRC.h + +#ifndef __INSTREAMWITHCRC_H +#define __INSTREAMWITHCRC_H + +#include "../../../Common/CRC.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; + CCRC _crc; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + _crc.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return _crc.GetDigest(); } + 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; + CCRC _crc; + bool _wasFinished; +public: + void SetStream(IInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + _crc.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return _crc.GetDigest(); } + 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 00000000..f7c3fcd9 --- /dev/null +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -0,0 +1,59 @@ +// Archive/Common/ItemNameUtils.cpp + +#include "StdAfx.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 = + #ifdef _WIN32 + 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 00000000..63a01563 --- /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/String.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 00000000..a8cb333e --- /dev/null +++ b/CPP/7zip/Archive/Common/MultiStream.cpp @@ -0,0 +1,201 @@ +// MultiStream.cpp + +#include "StdAfx.h" + +#include "MultiStream.h" + +STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if(processedSize != NULL) + *processedSize = 0; + while(_streamIndex < Streams.Size() && size > 0) + { + CSubStreamInfo &s = Streams[_streamIndex]; + if (_pos == s.Size) + { + _streamIndex++; + _pos = 0; + continue; + } + RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); + UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); + UInt32 realProcessed; + HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); + data = (void *)((Byte *)data + realProcessed); + size -= realProcessed; + if(processedSize != NULL) + *processedSize += realProcessed; + _pos += realProcessed; + _seekPos += realProcessed; + RINOK(result); + break; + } + return S_OK; +} + +STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, + UInt64 *newPosition) +{ + UInt64 newPos; + switch(seekOrigin) + { + case STREAM_SEEK_SET: + newPos = offset; + break; + case STREAM_SEEK_CUR: + newPos = _seekPos + offset; + break; + case STREAM_SEEK_END: + newPos = _totalLength + offset; + break; + default: + return STG_E_INVALIDFUNCTION; + } + _seekPos = 0; + for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) + { + UInt64 size = Streams[_streamIndex].Size; + if (newPos < _seekPos + size) + { + _pos = newPos - _seekPos; + _seekPos += _pos; + if (newPosition != 0) + *newPosition = newPos; + return S_OK; + } + _seekPos += size; + } + if (newPos == _seekPos) + { + if (newPosition != 0) + *newPosition = newPos; + return S_OK; + } + return E_FAIL; +} + + +/* +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 00000000..5a7cc687 --- /dev/null +++ b/CPP/7zip/Archive/Common/MultiStream.h @@ -0,0 +1,76 @@ +// MultiStream.h + +#ifndef __MULTISTREAM_H +#define __MULTISTREAM_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/Vector.h" +#include "../../Archive/IArchive.h" + +class CMultiStream: + public IInStream, + public CMyUnknownImp +{ + int _streamIndex; + UInt64 _pos; + UInt64 _seekPos; + UInt64 _totalLength; +public: + struct CSubStreamInfo + { + CMyComPtr<IInStream> Stream; + UInt64 Pos; + UInt64 Size; + }; + CObjectVector<CSubStreamInfo> Streams; + void Init() + { + _streamIndex = 0; + _pos = 0; + _seekPos = 0; + _totalLength = 0; + for (int i = 0; i < Streams.Size(); i++) + _totalLength += Streams[i].Size; + } + + 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 00000000..7ac3f123 --- /dev/null +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp @@ -0,0 +1,24 @@ +// OutStreamWithCRC.cpp + +#include "StdAfx.h" + +#include "OutStreamWithCRC.h" + +STDMETHODIMP COutStreamWithCRC::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); + if (_calculateCrc) + _crc.Update(data, realProcessedSize); + _size += realProcessedSize; + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h new file mode 100755 index 00000000..0feb542b --- /dev/null +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -0,0 +1,37 @@ +// OutStreamWithCRC.h + +#ifndef __OUTSTREAMWITHCRC_H +#define __OUTSTREAMWITHCRC_H + +#include "../../../Common/CRC.h" +#include "../../../Common/MyCom.h" +#include "../../IStream.h" + +class COutStreamWithCRC: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; + CCRC _crc; + bool _calculateCrc; +public: + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init(bool calculateCrc = true) + { + _size = 0; + _calculateCrc = calculateCrc; + _crc.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt64 GetSize() const { return _size; } + UInt32 GetCRC() const { return _crc.GetDigest(); } + void InitCRC() { _crc.Init(); } +}; + +#endif diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp new file mode 100755 index 00000000..9866d900 --- /dev/null +++ b/CPP/7zip/Archive/Common/ParseProperties.cpp @@ -0,0 +1,171 @@ +// 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); +} + +HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) +{ + switch(value.vt) + { + case VT_EMPTY: + dest = true; + break; + /* + case VT_UI4: + dest = (value.ulVal != 0); + break; + */ + case VT_BSTR: + { + UString valueString = value.bstrVal; + valueString.MakeUpper(); + if (valueString.Compare(L"ON") == 0) + dest = true; + else if (valueString.Compare(L"OFF") == 0) + dest = false; + else + return E_INVALIDARG; + break; + } + default: + return E_INVALIDARG; + } + return S_OK; +} + +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 00000000..e6db316b --- /dev/null +++ b/CPP/7zip/Archive/Common/ParseProperties.h @@ -0,0 +1,17 @@ +// ParseProperties.h + +#ifndef __PARSEPROPERTIES_H +#define __PARSEPROPERTIES_H + +#include "Common/String.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); + +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 00000000..2e4be10b --- /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 |