mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 03:15:00 -06:00
4.48 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
0b33f700a6
commit
fd8b1d78b4
19
CPP/7zip/Archive/Common/CoderMixer.cpp
Executable file
19
CPP/7zip/Archive/Common/CoderMixer.cpp
Executable file
@@ -0,0 +1,19 @@
|
||||
// CoderMixer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
InSizeAssigned = (inSize != 0);
|
||||
if (InSizeAssigned)
|
||||
InSizeValue = *inSize;
|
||||
OutSizeAssigned = (outSize != 0);
|
||||
if (OutSizeAssigned)
|
||||
OutSizeValue = *outSize;
|
||||
}
|
||||
|
||||
}
|
||||
32
CPP/7zip/Archive/Common/CoderMixer.h
Executable file
32
CPP/7zip/Archive/Common/CoderMixer.h
Executable file
@@ -0,0 +1,32 @@
|
||||
// CoderMixer.h
|
||||
|
||||
#ifndef __CODER_MIXER_H
|
||||
#define __CODER_MIXER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
struct CCoderInfo
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ISequentialInStream> InStream;
|
||||
CMyComPtr<ISequentialOutStream> OutStream;
|
||||
CMyComPtr<ICompressProgressInfo> Progress;
|
||||
|
||||
UInt64 InSizeValue;
|
||||
UInt64 OutSizeValue;
|
||||
bool InSizeAssigned;
|
||||
bool OutSizeAssigned;
|
||||
|
||||
void ReInit()
|
||||
{
|
||||
InSizeAssigned = OutSizeAssigned = false;
|
||||
}
|
||||
|
||||
void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
namespace NCoderMixer {
|
||||
|
||||
CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
_srcBindInfo(srcBindInfo)
|
||||
@@ -81,7 +81,7 @@ void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
|
||||
destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
|
||||
}
|
||||
|
||||
CCoderInfo::CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
NumInStreams(numInStreams),
|
||||
NumOutStreams(numOutStreams)
|
||||
{
|
||||
@@ -111,7 +111,7 @@ static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderInfo::SetCoderInfo(const UInt64 **inSizes,
|
||||
void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,
|
||||
const UInt64 **outSizes)
|
||||
{
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#ifndef __CODER_MIXER2_H
|
||||
#define __CODER_MIXER2_H
|
||||
|
||||
#include "../../../Common/Vector.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
#include "../../../Common/Types.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
namespace NCoderMixer {
|
||||
|
||||
struct CBindPair
|
||||
{
|
||||
@@ -127,7 +127,7 @@ struct CBindInfo
|
||||
class CBindReverseConverter
|
||||
{
|
||||
UInt32 _numSrcOutStreams;
|
||||
NCoderMixer2::CBindInfo _srcBindInfo;
|
||||
NCoderMixer::CBindInfo _srcBindInfo;
|
||||
CRecordVector<UInt32> _srcInToDestOutMap;
|
||||
CRecordVector<UInt32> _srcOutToDestInMap;
|
||||
CRecordVector<UInt32> _destInToSrcOutMap;
|
||||
@@ -135,11 +135,11 @@ public:
|
||||
UInt32 NumSrcInStreams;
|
||||
CRecordVector<UInt32> DestOutToSrcInMap;
|
||||
|
||||
CBindReverseConverter(const NCoderMixer2::CBindInfo &srcBindInfo);
|
||||
void CreateReverseBindInfo(NCoderMixer2::CBindInfo &destBindInfo);
|
||||
CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);
|
||||
void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
|
||||
};
|
||||
|
||||
struct CCoderInfo
|
||||
struct CCoderInfo2
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
@@ -151,8 +151,14 @@ struct CCoderInfo
|
||||
CRecordVector<const UInt64 *> InSizePointers;
|
||||
CRecordVector<const UInt64 *> OutSizePointers;
|
||||
|
||||
CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
|
||||
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
|
||||
|
||||
@@ -3,16 +3,11 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer2MT.h"
|
||||
#include "CrossThreadProgress.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NSynchronization;
|
||||
namespace NCoderMixer {
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
CThreadCoderInfo::CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
ExitEvent(NULL),
|
||||
CCoderInfo(numInStreams, numOutStreams)
|
||||
CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
CCoderInfo2(numInStreams, numOutStreams)
|
||||
{
|
||||
InStreams.Reserve(NumInStreams);
|
||||
InStreamPointers.Reserve(NumInStreams);
|
||||
@@ -20,62 +15,38 @@ CThreadCoderInfo::CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
OutStreamPointers.Reserve(NumOutStreams);
|
||||
}
|
||||
|
||||
class CCoderInfoFlusher2
|
||||
void CCoder2::Execute() { Code(NULL); }
|
||||
|
||||
void CCoder2::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
CThreadCoderInfo *m_CoderInfo;
|
||||
public:
|
||||
CCoderInfoFlusher2(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {}
|
||||
~CCoderInfoFlusher2()
|
||||
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]);
|
||||
}
|
||||
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 < 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();
|
||||
for (i = 0; i < InStreams.Size(); i++)
|
||||
InStreams[i].Release();
|
||||
for (i = 0; i < OutStreams.Size(); i++)
|
||||
OutStreams[i].Release();
|
||||
}
|
||||
};
|
||||
|
||||
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,
|
||||
@@ -99,54 +70,15 @@ static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
}
|
||||
|
||||
|
||||
void CThreadCoderInfo::SetCoderInfo(const UInt64 **inSizes,
|
||||
const UInt64 **outSizes, ICompressProgressInfo *progress)
|
||||
void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
{
|
||||
Progress = progress;
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
}
|
||||
|
||||
static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// CCoderMixer2MT
|
||||
|
||||
static THREAD_FUNC_DECL MainCoderThread(void *threadCoderInfo)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (!((CCoderMixer2MT *)threadCoderInfo)->MyCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CCoderMixer2MT::CCoderMixer2MT()
|
||||
{
|
||||
if (CreateEvents() != S_OK)
|
||||
throw 271824;
|
||||
if (_mainThread.Create(MainCoderThread, this) != S_OK)
|
||||
throw 271825;
|
||||
}
|
||||
|
||||
CCoderMixer2MT::~CCoderMixer2MT()
|
||||
{
|
||||
_exitEvent.Set();
|
||||
_mainThread.Wait();
|
||||
for(int i = 0; i < _threads.Size(); i++)
|
||||
{
|
||||
_threads[i].Wait();
|
||||
_threads[i].Close();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
_bindInfo = bindInfo;
|
||||
@@ -161,48 +93,23 @@ HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
|
||||
void CCoderMixer2MT::AddCoderCommon()
|
||||
{
|
||||
int index = _coderInfoVector.Size();
|
||||
const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index];
|
||||
|
||||
CThreadCoderInfo threadCoderInfo(CoderStreamsInfo.NumInStreams,
|
||||
CoderStreamsInfo.NumOutStreams);
|
||||
_coderInfoVector.Add(threadCoderInfo);
|
||||
CThreadCoderInfo *tci = &_coderInfoVector.Back();
|
||||
tci->CreateEvents();
|
||||
tci->ExitEvent = _exitEvent;
|
||||
|
||||
NWindows::CThread newThread;
|
||||
_threads.Add(newThread);
|
||||
if (_threads.Back().Create(CoderThread, tci) != S_OK)
|
||||
throw 271824;
|
||||
const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
|
||||
CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
|
||||
_coders.Add(threadCoderInfo);
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coderInfoVector.Back().Coder = coder;
|
||||
_coders.Back().Coder = coder;
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coderInfoVector.Back().Coder2 = coder;
|
||||
_coders.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()
|
||||
{
|
||||
@@ -211,17 +118,16 @@ void CCoderMixer2MT::ReInit()
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2MT::Init(ISequentialInStream **inStreams,
|
||||
ISequentialOutStream **outStreams)
|
||||
HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)
|
||||
{
|
||||
/*
|
||||
if (_coderInfoVector.Size() != _bindInfo.Coders.Size())
|
||||
if (_coders.Size() != _bindInfo.Coders.Size())
|
||||
throw 0;
|
||||
*/
|
||||
int i;
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
for(i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
CThreadCoderInfo &coderInfo = _coderInfoVector[i];
|
||||
CCoder2 &coderInfo = _coders[i];
|
||||
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
|
||||
coderInfo.InStreams.Clear();
|
||||
UInt32 j;
|
||||
@@ -241,45 +147,26 @@ STDMETHODIMP CCoderMixer2MT::Init(ISequentialInStream **inStreams,
|
||||
_bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
|
||||
|
||||
_streamBinders[i].CreateStreams(
|
||||
&_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
&_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex]);
|
||||
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
&_coders[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];
|
||||
_coders[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];
|
||||
_coders[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;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
_coderInfoVector[i].CompressEvent.Set();
|
||||
for (i = 0; i < _coderInfoVector.Size(); i++)
|
||||
_coderInfoVector[i].CompressionCompletedEvent.Lock();
|
||||
|
||||
_compressingFinishedEvent.Set();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
const UInt64 ** /* inSizes */,
|
||||
UInt32 numInStreams,
|
||||
@@ -294,56 +181,48 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
|
||||
Init(inStreams, outStreams);
|
||||
|
||||
_compressingFinishedEvent.Reset(); // ?
|
||||
|
||||
CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
|
||||
CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
|
||||
RINOK(progressSpec->Create());
|
||||
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++)
|
||||
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();
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coderInfoVector[i].Result;
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result == E_ABORT)
|
||||
return result;
|
||||
}
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result == S_FALSE)
|
||||
return result;
|
||||
}
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coderInfoVector[i].Result;
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK && result != E_FAIL)
|
||||
return result;
|
||||
}
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coderInfoVector[i].Result;
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UInt64 CCoderMixer2MT::GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
{
|
||||
return _streamBinders[binderIndex].ProcessedSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,73 +5,55 @@
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Windows/Thread.h"
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
namespace NCoderMixer {
|
||||
|
||||
// CreateEvents();
|
||||
// {
|
||||
// SetCoderInfo()
|
||||
// Init Streams
|
||||
// set CompressEvent()
|
||||
// wait CompressionCompletedEvent
|
||||
// }
|
||||
|
||||
struct CThreadCoderInfo: public CCoderInfo
|
||||
struct CCoder2: public CCoderInfo2, public CVirtThread
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent CompressEvent;
|
||||
HANDLE ExitEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent CompressionCompletedEvent;
|
||||
|
||||
HRESULT Result;
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
|
||||
CRecordVector<ISequentialInStream *> InStreamPointers;
|
||||
CRecordVector<ISequentialOutStream *> OutStreamPointers;
|
||||
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);
|
||||
bool WaitAndCode();
|
||||
HRes CreateEvents()
|
||||
{
|
||||
RINOK(CompressEvent.CreateIfNotCreated());
|
||||
return CompressionCompletedEvent.CreateIfNotCreated();
|
||||
}
|
||||
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]()
|
||||
// }
|
||||
//
|
||||
// for each file
|
||||
// {
|
||||
// ReInit()
|
||||
// for each coder
|
||||
// {
|
||||
// SetCoderInfo
|
||||
// }
|
||||
// SetProgressIndex(UInt32 coderIndex);
|
||||
// Code
|
||||
// }
|
||||
|
||||
/*
|
||||
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
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
CBindInfo _bindInfo;
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
int _progressCoderIndex;
|
||||
|
||||
void AddCoderCommon();
|
||||
HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
|
||||
public:
|
||||
STDMETHOD(Init)(ISequentialInStream **inStreams,
|
||||
ISequentialOutStream **outStreams);
|
||||
CObjectVector<CCoder2> _coders;
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream **inStreams,
|
||||
const UInt64 **inSizes,
|
||||
@@ -81,50 +63,17 @@ public:
|
||||
UInt32 numOutStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
|
||||
CCoderMixer2MT();
|
||||
~CCoderMixer2MT();
|
||||
void AddCoderCommon();
|
||||
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)
|
||||
{ _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;
|
||||
NWindows::NSynchronization::CAutoResetEvent _compressingFinishedEvent;
|
||||
|
||||
NWindows::NSynchronization::CManualResetEvent _exitEvent;
|
||||
UInt32 _progressCoderIndex;
|
||||
|
||||
HRes CreateEvents()
|
||||
{
|
||||
RINOK(_startCompressingEvent.CreateIfNotCreated());
|
||||
RINOK(_compressingFinishedEvent.CreateIfNotCreated());
|
||||
return _exitEvent.CreateIfNotCreated();
|
||||
}
|
||||
|
||||
public:
|
||||
HRESULT SetBindInfo(const CBindInfo &bindInfo);
|
||||
|
||||
{ _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
|
||||
UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
{ return _streamBinders[binderIndex].ProcessedSize; }
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
97
CPP/7zip/Archive/Common/CoderMixerMT.cpp
Executable file
97
CPP/7zip/Archive/Common/CoderMixerMT.cpp
Executable file
@@ -0,0 +1,97 @@
|
||||
// CoderMixerMT.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixerMT.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
void CCoder::Execute() { Code(NULL); }
|
||||
|
||||
void CCoder::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
Result = Coder->Code(InStream, OutStream,
|
||||
InSizeAssigned ? &InSizeValue : NULL,
|
||||
OutSizeAssigned ? &OutSizeValue : NULL,
|
||||
progress);
|
||||
InStream.Release();
|
||||
OutStream.Release();
|
||||
}
|
||||
|
||||
void CCoderMixerMT::AddCoder(ICompressCoder *coder)
|
||||
{
|
||||
_coders.Add(CCoder());
|
||||
_coders.Back().Coder = coder;
|
||||
}
|
||||
|
||||
void CCoderMixerMT::ReInit()
|
||||
{
|
||||
for(int i = 0; i < _coders.Size(); i++)
|
||||
_coders[i].ReInit();
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
_coders.Front().InStream = inStream;
|
||||
int i;
|
||||
_coders.Back().OutStream = outStream;
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
{
|
||||
RINOK(_coders[i].Create());
|
||||
}
|
||||
|
||||
while (_streamBinders.Size() + 1 < _coders.Size())
|
||||
{
|
||||
_streamBinders.Add(CStreamBinder());
|
||||
int i = _streamBinders.Size() - 1;
|
||||
CStreamBinder &sb = _streamBinders.Back();
|
||||
RINOK(sb.CreateEvents());
|
||||
sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
|
||||
}
|
||||
|
||||
for(i = 0; i < _streamBinders.Size(); i++)
|
||||
_streamBinders[i].ReInit();
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
_coders[i].Start();
|
||||
|
||||
_coders[_progressCoderIndex].Code(progress);
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
_coders[i].WaitFinish();
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result == E_ABORT)
|
||||
return result;
|
||||
}
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result == S_FALSE)
|
||||
return result;
|
||||
}
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK && result != E_FAIL)
|
||||
return result;
|
||||
}
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}
|
||||
68
CPP/7zip/Archive/Common/CoderMixerMT.h
Executable file
68
CPP/7zip/Archive/Common/CoderMixerMT.h
Executable file
@@ -0,0 +1,68 @@
|
||||
// CoderMixerMT.h
|
||||
|
||||
#ifndef __CODER_MIXER_MT_H
|
||||
#define __CODER_MIXER_MT_H
|
||||
|
||||
#include "../../../Common/Vector.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
#include "CoderMixer.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
struct CCoder: public CCoderInfo, public CVirtThread
|
||||
{
|
||||
HRESULT Result;
|
||||
|
||||
virtual void Execute();
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
/*
|
||||
for each coder
|
||||
AddCoder()
|
||||
SetProgressIndex(UInt32 coderIndex);
|
||||
|
||||
for each file
|
||||
{
|
||||
ReInit()
|
||||
for each coder
|
||||
SetCoderInfo
|
||||
Code
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
class CCoderMixerMT:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
int _progressCoderIndex;
|
||||
|
||||
public:
|
||||
CObjectVector<CCoder> _coders;
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
void AddCoder(ICompressCoder *coder);
|
||||
void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; }
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize)
|
||||
{ _coders[coderIndex].SetCoderInfo(inSize, outSize); }
|
||||
|
||||
/*
|
||||
UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
{ return _streamBinders[binderIndex].ProcessedSize; }
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
609
CPP/7zip/Archive/Common/HandlerOut.cpp
Executable file
609
CPP/7zip/Archive/Common/HandlerOut.cpp
Executable file
@@ -0,0 +1,609 @@
|
||||
// HandlerOutCommon.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "HandlerOut.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../Common/ParseProperties.h"
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
#include "../../../Windows/System.h"
|
||||
#endif
|
||||
|
||||
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); }
|
||||
|
||||
static inline bool IsLZMAMethod(const UString &methodName)
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
CNameToPropID g_NameToPropID[] =
|
||||
{
|
||||
{ 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" }
|
||||
};
|
||||
|
||||
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 FindPropIdFromStringName(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 void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID,
|
||||
const NWindows::NCOM::CPropVariant &value)
|
||||
{
|
||||
for (int j = 0; j < oneMethodInfo.Properties.Size(); j++)
|
||||
if (oneMethodInfo.Properties[j].Id == propID)
|
||||
return;
|
||||
CProp property;
|
||||
property.Id = propID;
|
||||
property.Value = value;
|
||||
oneMethodInfo.Properties.Add(property);
|
||||
}
|
||||
|
||||
void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
||||
#ifdef COMPRESS_MT
|
||||
, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
UInt32 level = _level;
|
||||
if (oneMethodInfo.MethodName.IsEmpty())
|
||||
oneMethodInfo.MethodName = kDefaultMethodName;
|
||||
|
||||
if (IsLZMAMethod(oneMethodInfo.MethodName))
|
||||
{
|
||||
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);
|
||||
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
|
||||
#ifdef COMPRESS_MT
|
||||
SetOneMethodProp(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);
|
||||
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
|
||||
SetOneMethodProp(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));
|
||||
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
|
||||
#ifdef COMPRESS_MT
|
||||
SetOneMethodProp(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)));
|
||||
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
|
||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
|
||||
}
|
||||
}
|
||||
|
||||
static void SplitParams(const UString &srcString, UStringVector &subStrings)
|
||||
{
|
||||
subStrings.Clear();
|
||||
UString name;
|
||||
int len = srcString.Length();
|
||||
if (len == 0)
|
||||
return;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = srcString[i];
|
||||
if (c == L':')
|
||||
{
|
||||
subStrings.Add(name);
|
||||
name.Empty();
|
||||
}
|
||||
else
|
||||
name += c;
|
||||
}
|
||||
subStrings.Add(name);
|
||||
}
|
||||
|
||||
static void SplitParam(const UString ¶m, UString &name, UString &value)
|
||||
{
|
||||
int eqPos = param.Find(L'=');
|
||||
if (eqPos >= 0)
|
||||
{
|
||||
name = param.Left(eqPos);
|
||||
value = param.Mid(eqPos + 1);
|
||||
return;
|
||||
}
|
||||
for(int i = 0; i < param.Length(); i++)
|
||||
{
|
||||
wchar_t c = param[i];
|
||||
if (c >= L'0' && c <= L'9')
|
||||
{
|
||||
name = param.Left(i);
|
||||
value = param.Mid(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
name = param;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
|
||||
{
|
||||
CProp property;
|
||||
if (
|
||||
name.CompareNoCase(L"D") == 0 ||
|
||||
name.CompareNoCase(L"MEM") == 0)
|
||||
{
|
||||
UInt32 dicSize;
|
||||
RINOK(ParsePropDictionaryValue(value, dicSize));
|
||||
if (name.CompareNoCase(L"D") == 0)
|
||||
property.Id = NCoderPropID::kDictionarySize;
|
||||
else
|
||||
property.Id = NCoderPropID::kUsedMemorySize;
|
||||
property.Value = dicSize;
|
||||
oneMethodInfo.Properties.Add(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = FindPropIdFromStringName(name);
|
||||
if (index < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
||||
property.Id = nameToPropID.PropID;
|
||||
|
||||
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, property.Value))
|
||||
return E_INVALIDARG;
|
||||
|
||||
oneMethodInfo.Properties.Add(property);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
|
||||
{
|
||||
UStringVector params;
|
||||
SplitParams(srcString, params);
|
||||
if (params.Size() > 0)
|
||||
oneMethodInfo.MethodName = params[0];
|
||||
for (int i = 1; i < params.Size(); i++)
|
||||
{
|
||||
const UString ¶m = params[i];
|
||||
UString name, value;
|
||||
SplitParam(param, name, value);
|
||||
RINOK(SetParam(oneMethodInfo, name, value));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetSolidSettings(const UString &s)
|
||||
{
|
||||
bool res;
|
||||
if (StringToBool(s, res))
|
||||
{
|
||||
if (res)
|
||||
InitSolid();
|
||||
else
|
||||
_numSolidFiles = 1;
|
||||
return S_OK;
|
||||
}
|
||||
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)
|
||||
{
|
||||
switch(value.vt)
|
||||
{
|
||||
case VT_EMPTY:
|
||||
InitSolid();
|
||||
return S_OK;
|
||||
case VT_BSTR:
|
||||
return SetSolidSettings(value.bstrVal);
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
void COutHandler::Init()
|
||||
{
|
||||
_removeSfxBlock = false;
|
||||
_compressHeaders = true;
|
||||
_encryptHeaders = false;
|
||||
|
||||
WriteModified = true;
|
||||
WriteCreated = false;
|
||||
WriteAccessed = false;
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
_numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
#endif
|
||||
|
||||
_level = 5;
|
||||
_autoFilter = true;
|
||||
_volumeMode = false;
|
||||
InitSolid();
|
||||
}
|
||||
|
||||
void COutHandler::BeforeSetProperty()
|
||||
{
|
||||
Init();
|
||||
#ifdef COMPRESS_MT
|
||||
numProcessors = NSystem::GetNumberOfProcessors();
|
||||
#endif
|
||||
|
||||
mainDicSize = 0xFFFFFFFF;
|
||||
mainDicMethodIndex = 0xFFFFFFFF;
|
||||
minNumber = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
UString realName = name.Mid(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if(name.Left(2).CompareNoCase(L"MT") == 0)
|
||||
{
|
||||
#ifdef COMPRESS_MT
|
||||
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)
|
||||
return SetBoolProperty(_encryptHeaders, value);
|
||||
if (name.CompareNoCase(L"TM") == 0)
|
||||
return SetBoolProperty(WriteModified, value);
|
||||
if (name.CompareNoCase(L"TC") == 0)
|
||||
return SetBoolProperty(WriteCreated, value);
|
||||
if (name.CompareNoCase(L"TA") == 0)
|
||||
return SetBoolProperty(WriteAccessed, 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
|
||||
{
|
||||
CProp property;
|
||||
if (realName.Left(1).CompareNoCase(L"D") == 0)
|
||||
{
|
||||
UInt32 dicSize;
|
||||
RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
|
||||
property.Id = NCoderPropID::kDictionarySize;
|
||||
property.Value = dicSize;
|
||||
oneMethodInfo.Properties.Add(property);
|
||||
if (number <= mainDicMethodIndex)
|
||||
mainDicSize = dicSize;
|
||||
}
|
||||
else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
|
||||
{
|
||||
UInt32 dicSize;
|
||||
RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
|
||||
property.Id = NCoderPropID::kUsedMemorySize;
|
||||
property.Value = dicSize;
|
||||
oneMethodInfo.Properties.Add(property);
|
||||
if (number <= mainDicMethodIndex)
|
||||
mainDicSize = dicSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = FindPropIdFromStringName(realName);
|
||||
if (index < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
||||
property.Id = nameToPropID.PropID;
|
||||
|
||||
if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
|
||||
return E_INVALIDARG;
|
||||
|
||||
oneMethodInfo.Properties.Add(property);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}
|
||||
84
CPP/7zip/Archive/Common/HandlerOut.h
Executable file
84
CPP/7zip/Archive/Common/HandlerOut.h
Executable file
@@ -0,0 +1,84 @@
|
||||
// HandlerOut.h
|
||||
|
||||
#ifndef __HANDLER_OUT_H
|
||||
#define __HANDLER_OUT_H
|
||||
|
||||
#include "../../Common/MethodProps.h"
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
struct COneMethodInfo
|
||||
{
|
||||
CObjectVector<CProp> Properties;
|
||||
UString MethodName;
|
||||
};
|
||||
|
||||
class COutHandler
|
||||
{
|
||||
public:
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
|
||||
HRESULT SetSolidSettings(const UString &s);
|
||||
HRESULT SetSolidSettings(const PROPVARIANT &value);
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
UInt32 _numThreads;
|
||||
#endif
|
||||
|
||||
CObjectVector<COneMethodInfo> _methods;
|
||||
bool _removeSfxBlock;
|
||||
|
||||
UInt64 _numSolidFiles;
|
||||
UInt64 _numSolidBytes;
|
||||
bool _numSolidBytesDefined;
|
||||
bool _solidExtension;
|
||||
|
||||
bool _compressHeaders;
|
||||
bool _encryptHeaders;
|
||||
|
||||
bool WriteModified;
|
||||
bool WriteCreated;
|
||||
bool WriteAccessed;
|
||||
|
||||
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
|
||||
#ifdef COMPRESS_MT
|
||||
, 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;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifndef __ARCHIVE_ITEMNAMEUTILS_H
|
||||
#define __ARCHIVE_ITEMNAMEUTILS_H
|
||||
|
||||
#include "../../../Common/String.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define __MULTISTREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/Vector.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
class CMultiStream:
|
||||
|
||||
@@ -97,34 +97,37 @@ HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, U
|
||||
return ParsePropDictionaryValue(name, resValue);
|
||||
}
|
||||
|
||||
bool StringToBool(const UString &s, bool &res)
|
||||
{
|
||||
if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0)
|
||||
{
|
||||
res = true;
|
||||
return true;
|
||||
}
|
||||
if (s.CompareNoCase(L"OFF") == 0)
|
||||
{
|
||||
res = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
|
||||
{
|
||||
switch(value.vt)
|
||||
{
|
||||
case VT_EMPTY:
|
||||
dest = true;
|
||||
break;
|
||||
return S_OK;
|
||||
/*
|
||||
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 StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG;
|
||||
}
|
||||
return S_OK;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
int ParseStringToUInt32(const UString &srcString, UInt32 &number)
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
#ifndef __PARSEPROPERTIES_H
|
||||
#define __PARSEPROPERTIES_H
|
||||
|
||||
#include "Common/String.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);
|
||||
|
||||
Reference in New Issue
Block a user