mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-14 20:11:38 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
@@ -1,7 +1,5 @@
|
||||
// CodecsPath.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __CODECSPATH_H
|
||||
#define __CODECSPATH_H
|
||||
|
||||
|
||||
31
7zip/Archive/Common/CoderLoader.cpp
Executable file
31
7zip/Archive/Common/CoderLoader.cpp
Executable file
@@ -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;
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
// CoderLoader.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __CODERLOADER_H
|
||||
#define __CODERLOADER_H
|
||||
|
||||
#include "../../../Common/String.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Windows/DLL.h"
|
||||
// #include "../../../Windows/Defs.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
typedef UINT32 (WINAPI * CreateObjectPointer)(
|
||||
typedef UInt32 (WINAPI * CreateObjectPointer)(
|
||||
const GUID *clsID,
|
||||
const GUID *interfaceID,
|
||||
void **outObject);
|
||||
@@ -18,14 +16,38 @@ typedef UINT32 (WINAPI * CreateObjectPointer)(
|
||||
class CCoderLibrary: public NWindows::NDLL::CLibrary
|
||||
{
|
||||
public:
|
||||
HRESULT CreateCoder(REFGUID clsID, ICompressCoder **coder)
|
||||
HRESULT CreateObject(REFGUID clsID, REFGUID iid, void **obj)
|
||||
{
|
||||
CreateObjectPointer createObject = (CreateObjectPointer)
|
||||
GetProcAddress("CreateObject");
|
||||
GetProcAddress("CreateObject");
|
||||
if (createObject == NULL)
|
||||
return GetLastError();
|
||||
return createObject(&clsID, &IID_ICompressCoder, (void **)coder);
|
||||
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;
|
||||
@@ -35,6 +57,8 @@ public:
|
||||
Attach(libTemp.Detach());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder);
|
||||
HRESULT CreateCoder2(REFGUID clsID, ICompressCoder2 **coder)
|
||||
{
|
||||
CreateObjectPointer createObject = (CreateObjectPointer)
|
||||
@@ -87,6 +111,21 @@ public:
|
||||
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);
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
// CoderMixer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer.h"
|
||||
#include "Common/Defs.h"
|
||||
#include "CrossThreadProgress.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NSynchronization;
|
||||
|
||||
//////////////////////////
|
||||
// CThreadCoderInfo
|
||||
|
||||
void CThreadCoderInfo::CreateEvents()
|
||||
{
|
||||
CompressEvent = new CAutoResetEvent(false);
|
||||
CompressionCompletedEvent = new CAutoResetEvent(false);
|
||||
}
|
||||
|
||||
CThreadCoderInfo::~CThreadCoderInfo()
|
||||
{
|
||||
if (CompressEvent != NULL)
|
||||
delete CompressEvent;
|
||||
if (CompressionCompletedEvent != NULL)
|
||||
delete CompressionCompletedEvent;
|
||||
}
|
||||
|
||||
class CCoderInfoFlusher
|
||||
{
|
||||
CThreadCoderInfo *m_CoderInfo;
|
||||
public:
|
||||
CCoderInfoFlusher(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {}
|
||||
~CCoderInfoFlusher()
|
||||
{
|
||||
m_CoderInfo->InStream.Release();
|
||||
m_CoderInfo->OutStream.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;
|
||||
|
||||
{
|
||||
CCoderInfoFlusher coderInfoFlusher(this);
|
||||
Result = Coder->Code(InStream, OutStream,
|
||||
InSizeAssigned ? &InSizeValue : NULL,
|
||||
OutSizeAssigned ? &OutSizeValue : NULL,
|
||||
Progress);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// CCoderMixer
|
||||
|
||||
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (!((CCoderMixer *)threadCoderInfo)->MyCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CCoderMixer::CCoderMixer()
|
||||
{
|
||||
if (!m_MainThread.Create(MainCoderThread, this))
|
||||
throw 271825;
|
||||
}
|
||||
|
||||
CCoderMixer::~CCoderMixer()
|
||||
{
|
||||
ExitEvent.Set();
|
||||
::WaitForSingleObject(m_MainThread, INFINITE);
|
||||
DWORD result = ::WaitForMultipleObjects(m_Threads.Size(),
|
||||
&m_Threads.Front(), TRUE, INFINITE);
|
||||
for(int i = 0; i < m_Threads.Size(); i++)
|
||||
::CloseHandle(m_Threads[i]);
|
||||
}
|
||||
|
||||
|
||||
void CCoderMixer::AddCoder(ICompressCoder *coder)
|
||||
{
|
||||
CThreadCoderInfo threadCoderInfo;
|
||||
threadCoderInfo.Coder = coder;
|
||||
m_CoderInfoVector.Add(threadCoderInfo);
|
||||
m_CoderInfoVector.Back().CreateEvents();
|
||||
m_CoderInfoVector.Back().ExitEvent = ExitEvent;
|
||||
m_CompressingCompletedEvents.Add(*m_CoderInfoVector.Back().CompressionCompletedEvent);
|
||||
}
|
||||
|
||||
void CCoderMixer::FinishAddingCoders()
|
||||
{
|
||||
for(int i = 0; i < m_CoderInfoVector.Size(); i++)
|
||||
{
|
||||
DWORD id;
|
||||
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
|
||||
&m_CoderInfoVector[i], 0, &id);
|
||||
if (newThread == 0)
|
||||
throw 271824;
|
||||
m_Threads.Add(newThread);
|
||||
if (i >= 1)
|
||||
{
|
||||
CStreamBinder streamBinder;
|
||||
m_StreamBinders.Add(streamBinder);
|
||||
m_StreamBinders.Back().CreateEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderMixer::ReInit()
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < m_CoderInfoVector.Size(); i++)
|
||||
{
|
||||
CThreadCoderInfo &coderInfo = m_CoderInfoVector[i];
|
||||
coderInfo.InSizeAssigned = false;
|
||||
coderInfo.OutSizeAssigned = false;
|
||||
coderInfo.Progress = NULL;
|
||||
}
|
||||
for(i = 0; i < m_StreamBinders.Size(); i++)
|
||||
{
|
||||
m_StreamBinders[i].ReInit();
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderMixer::SetCoderInfo(UINT32 coderIndex, const UINT64 *inSize,
|
||||
const UINT64 *outSize)
|
||||
{
|
||||
CThreadCoderInfo &coderInfo = m_CoderInfoVector[coderIndex];
|
||||
|
||||
coderInfo.InSizeAssigned = (inSize != NULL);
|
||||
if (coderInfo.InSizeAssigned)
|
||||
coderInfo.InSizeValue = *inSize;
|
||||
|
||||
coderInfo.OutSizeAssigned = (outSize != NULL);
|
||||
if (coderInfo.OutSizeAssigned)
|
||||
coderInfo.OutSizeValue = *outSize;
|
||||
|
||||
coderInfo.Progress = NULL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoderMixer::Init(ISequentialInStream *inStreamMain,
|
||||
ISequentialOutStream *outStreamMain)
|
||||
{
|
||||
m_CoderInfoVector.Front().InStream = inStreamMain;
|
||||
for(int i = 0; i < m_StreamBinders.Size(); i++)
|
||||
m_StreamBinders[i].CreateStreams(&m_CoderInfoVector[i+1].InStream,
|
||||
&m_CoderInfoVector[i].OutStream);
|
||||
m_CoderInfoVector.Back().OutStream = outStreamMain;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool CCoderMixer::MyCode()
|
||||
{
|
||||
HANDLE events[2] = { ExitEvent, m_StartCompressingEvent };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
if (waitResult == WAIT_OBJECT_0 + 0)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < m_CoderInfoVector.Size(); i++)
|
||||
m_CoderInfoVector[i].CompressEvent->Set();
|
||||
DWORD result = ::WaitForMultipleObjects(m_CompressingCompletedEvents.Size(),
|
||||
&m_CompressingCompletedEvents.Front(), TRUE, INFINITE);
|
||||
|
||||
m_CompressingFinishedEvent.Set();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoderMixer::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
Init(inStream, outStream);
|
||||
|
||||
m_CompressingFinishedEvent.Reset(); // ?
|
||||
|
||||
CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
|
||||
CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
|
||||
progressSpec->Init();
|
||||
m_CoderInfoVector[m_ProgressCoderIndex].Progress = crossProgress;
|
||||
|
||||
m_StartCompressingEvent.Set();
|
||||
|
||||
while (true)
|
||||
{
|
||||
HANDLE events[2] = {m_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 < m_CoderInfoVector.Size(); i++)
|
||||
{
|
||||
HRESULT result = m_CoderInfoVector[i].Result;
|
||||
if (result == S_FALSE)
|
||||
return result;
|
||||
}
|
||||
for(i = 0; i < m_CoderInfoVector.Size(); i++)
|
||||
{
|
||||
HRESULT result = m_CoderInfoVector[i].Result;
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UINT64 CCoderMixer::GetWriteProcessedSize(UINT32 coderIndex)
|
||||
{
|
||||
return m_StreamBinders[coderIndex].ProcessedSize;
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
// CoderMixer.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __CODERMIXER_H
|
||||
#define __CODERMIXER_H
|
||||
|
||||
#include "Common/Vector.h"
|
||||
#include "Common/MyCom.h"
|
||||
#include "Windows/Thread.h"
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
struct CThreadCoderInfo
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent *CompressEvent;
|
||||
HANDLE ExitEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent;
|
||||
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ISequentialInStream> InStream;
|
||||
CMyComPtr<ISequentialOutStream> OutStream;
|
||||
UINT64 InSizeValue;
|
||||
UINT64 OutSizeValue;
|
||||
bool InSizeAssigned;
|
||||
bool OutSizeAssigned;
|
||||
ICompressProgressInfo *Progress;
|
||||
HRESULT Result;
|
||||
|
||||
CThreadCoderInfo(): ExitEvent(NULL), CompressEvent(NULL),
|
||||
CompressionCompletedEvent(NULL),
|
||||
InSizeAssigned(false),
|
||||
OutSizeAssigned(false), Progress(NULL){}
|
||||
~CThreadCoderInfo();
|
||||
bool WaitAndCode();
|
||||
void CreateEvents();
|
||||
};
|
||||
|
||||
|
||||
class CCoderMixer:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
public:
|
||||
STDMETHOD(Init)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream);
|
||||
// STDMETHOD(ReleaseStreams)();
|
||||
// STDMETHOD(Code)(UINT32 size, UINT32 &processedSize);
|
||||
// STDMETHOD(Flush)();
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
|
||||
CCoderMixer();
|
||||
~CCoderMixer();
|
||||
void AddCoder(ICompressCoder *aCoder);
|
||||
void FinishAddingCoders();
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UINT32 coderIndex,
|
||||
const UINT64 *inSize, const UINT64 *outSize);
|
||||
void SetProgressCoderIndex(UINT32 coderIndex)
|
||||
{ m_ProgressCoderIndex = coderIndex; }
|
||||
UINT64 GetWriteProcessedSize(UINT32 coderIndex);
|
||||
|
||||
bool MyCode();
|
||||
private:
|
||||
CObjectVector<CStreamBinder> m_StreamBinders;
|
||||
CObjectVector<CThreadCoderInfo> m_CoderInfoVector;
|
||||
CRecordVector<HANDLE> m_Threads;
|
||||
NWindows::CThread m_MainThread;
|
||||
|
||||
NWindows::NSynchronization::CAutoResetEvent m_StartCompressingEvent;
|
||||
CRecordVector<HANDLE> m_CompressingCompletedEvents;
|
||||
NWindows::NSynchronization::CAutoResetEvent m_CompressingFinishedEvent;
|
||||
|
||||
NWindows::NSynchronization::CManualResetEvent ExitEvent;
|
||||
UINT32 m_ProgressCoderIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
#include "CrossThreadProgress.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NSynchronization;
|
||||
|
||||
//////////////////////////
|
||||
// CThreadCoderInfo2
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
@@ -18,7 +11,7 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
{
|
||||
srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
|
||||
|
||||
UINT32 j;
|
||||
UInt32 j;
|
||||
for (j = 0; j < NumSrcInStreams; j++)
|
||||
{
|
||||
_srcInToDestOutMap.Add(0);
|
||||
@@ -30,10 +23,10 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
_destInToSrcOutMap.Add(0);
|
||||
}
|
||||
|
||||
UINT32 destInOffset = 0;
|
||||
UINT32 destOutOffset = 0;
|
||||
UINT32 srcInOffset = NumSrcInStreams;
|
||||
UINT32 srcOutOffset = _numSrcOutStreams;
|
||||
UInt32 destInOffset = 0;
|
||||
UInt32 destOutOffset = 0;
|
||||
UInt32 srcInOffset = NumSrcInStreams;
|
||||
UInt32 srcOutOffset = _numSrcOutStreams;
|
||||
|
||||
for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -42,16 +35,16 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
srcInOffset -= srcCoderInfo.NumInStreams;
|
||||
srcOutOffset -= srcCoderInfo.NumOutStreams;
|
||||
|
||||
UINT32 j;
|
||||
UInt32 j;
|
||||
for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
|
||||
{
|
||||
UINT32 index = srcInOffset + j;
|
||||
UInt32 index = srcInOffset + j;
|
||||
_srcInToDestOutMap[index] = destOutOffset;
|
||||
DestOutToSrcInMap[destOutOffset] = index;
|
||||
}
|
||||
for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
|
||||
{
|
||||
UINT32 index = srcOutOffset + j;
|
||||
UInt32 index = srcOutOffset + j;
|
||||
_srcOutToDestInMap[index] = destInOffset;
|
||||
_destInToSrcOutMap[destInOffset] = index;
|
||||
}
|
||||
@@ -88,102 +81,22 @@ void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
|
||||
destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
|
||||
}
|
||||
|
||||
|
||||
CThreadCoderInfo2::CThreadCoderInfo2(UINT32 numInStreams, UINT32 numOutStreams):
|
||||
ExitEvent(NULL),
|
||||
CompressEvent(NULL),
|
||||
CompressionCompletedEvent(NULL),
|
||||
CCoderInfo::CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
NumInStreams(numInStreams),
|
||||
NumOutStreams(numOutStreams)
|
||||
{
|
||||
InStreams.Reserve(NumInStreams);
|
||||
InStreamPointers.Reserve(NumInStreams);
|
||||
InSizes.Reserve(NumInStreams);
|
||||
InSizePointers.Reserve(NumInStreams);
|
||||
OutStreams.Reserve(NumOutStreams);
|
||||
OutStreamPointers.Reserve(NumOutStreams);
|
||||
OutSizes.Reserve(NumOutStreams);
|
||||
OutSizePointers.Reserve(NumOutStreams);
|
||||
OutSizePointers.Reserve(NumOutStreams);
|
||||
}
|
||||
|
||||
void CThreadCoderInfo2::CreateEvents()
|
||||
{
|
||||
CompressEvent = new CAutoResetEvent(false);
|
||||
CompressionCompletedEvent = new CAutoResetEvent(false);
|
||||
}
|
||||
|
||||
CThreadCoderInfo2::~CThreadCoderInfo2()
|
||||
{
|
||||
if (CompressEvent != NULL)
|
||||
delete CompressEvent;
|
||||
if (CompressionCompletedEvent != NULL)
|
||||
delete CompressionCompletedEvent;
|
||||
}
|
||||
|
||||
class CCoderInfoFlusher2
|
||||
{
|
||||
CThreadCoderInfo2 *m_CoderInfo;
|
||||
public:
|
||||
CCoderInfoFlusher2(CThreadCoderInfo2 *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 CThreadCoderInfo2::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 (CompressorIsCoder2)
|
||||
Result = Coder2->Code(&InStreamPointers.Front(),
|
||||
&InSizePointers.Front(),
|
||||
NumInStreams,
|
||||
&OutStreamPointers.Front(),
|
||||
&OutSizePointers.Front(),
|
||||
NumOutStreams,
|
||||
Progress);
|
||||
else
|
||||
Result = Coder->Code(InStreamPointers[0],
|
||||
OutStreamPointers[0],
|
||||
InSizePointers[0],
|
||||
OutSizePointers[0],
|
||||
Progress);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetSizes(const UINT64 **srcSizes, CRecordVector<UINT64> &sizes,
|
||||
CRecordVector<const UINT64 *> &sizePointers, UINT32 numItems)
|
||||
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++)
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (srcSizes == 0 || srcSizes[i] == NULL)
|
||||
{
|
||||
@@ -198,251 +111,11 @@ void SetSizes(const UINT64 **srcSizes, CRecordVector<UINT64> &sizes,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CThreadCoderInfo2::SetCoderInfo(const UINT64 **inSizes,
|
||||
const UINT64 **outSizes, ICompressProgressInfo *progress)
|
||||
void CCoderInfo::SetCoderInfo(const UInt64 **inSizes,
|
||||
const UInt64 **outSizes)
|
||||
{
|
||||
Progress = progress;
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
}
|
||||
|
||||
static DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (!((CThreadCoderInfo2 *)threadCoderInfo)->WaitAndCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// CCoderMixer2
|
||||
|
||||
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (!((CCoderMixer2 *)threadCoderInfo)->MyCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CCoderMixer2::CCoderMixer2()
|
||||
{
|
||||
if (!_mainThread.Create(MainCoderThread, this))
|
||||
throw 271825;
|
||||
}
|
||||
|
||||
CCoderMixer2::~CCoderMixer2()
|
||||
{
|
||||
_exitEvent.Set();
|
||||
|
||||
::WaitForSingleObject(_mainThread, INFINITE);
|
||||
DWORD result = ::WaitForMultipleObjects(_threads.Size(),
|
||||
&_threads.Front(), TRUE, INFINITE);
|
||||
for(int i = 0; i < _threads.Size(); i++)
|
||||
::CloseHandle(_threads[i]);
|
||||
}
|
||||
|
||||
void CCoderMixer2::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
_bindInfo = bindInfo;
|
||||
_streamBinders.Clear();
|
||||
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
|
||||
{
|
||||
_streamBinders.Add(CStreamBinder());
|
||||
_streamBinders.Back().CreateEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderMixer2::AddCoderCommon()
|
||||
{
|
||||
int index = _coderInfoVector.Size();
|
||||
const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index];
|
||||
|
||||
CThreadCoderInfo2 threadCoderInfo(CoderStreamsInfo.NumInStreams,
|
||||
CoderStreamsInfo.NumOutStreams);
|
||||
_coderInfoVector.Add(threadCoderInfo);
|
||||
_coderInfoVector.Back().CreateEvents();
|
||||
_coderInfoVector.Back().ExitEvent = _exitEvent;
|
||||
_compressingCompletedEvents.Add(*_coderInfoVector.Back().CompressionCompletedEvent);
|
||||
|
||||
DWORD id;
|
||||
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
|
||||
&_coderInfoVector.Back(), 0, &id);
|
||||
if (newThread == 0)
|
||||
throw 271824;
|
||||
_threads.Add(newThread);
|
||||
}
|
||||
|
||||
void CCoderMixer2::AddCoder(ICompressCoder *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coderInfoVector.Back().CompressorIsCoder2 = false;
|
||||
_coderInfoVector.Back().Coder = coder;
|
||||
}
|
||||
|
||||
void CCoderMixer2::AddCoder2(ICompressCoder2 *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coderInfoVector.Back().CompressorIsCoder2 = true;
|
||||
_coderInfoVector.Back().Coder2 = coder;
|
||||
}
|
||||
|
||||
/*
|
||||
void CCoderMixer2::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 CCoderMixer2::ReInit()
|
||||
{
|
||||
for(int i = 0; i < _streamBinders.Size(); i++)
|
||||
_streamBinders[i].ReInit();
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2::Init(ISequentialInStream **inStreams,
|
||||
ISequentialOutStream **outStreams)
|
||||
{
|
||||
if (_coderInfoVector.Size() != _bindInfo.Coders.Size())
|
||||
throw 0;
|
||||
UINT32 numInStreams = 0, numOutStreams = 0;
|
||||
int i;
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
{
|
||||
CThreadCoderInfo2 &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 CCoderMixer2::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 CCoderMixer2::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();
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
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 CCoderMixer2::GetWriteProcessedSize(UINT32 binderIndex) const
|
||||
{
|
||||
return _streamBinders[binderIndex].ProcessedSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,49 +1,54 @@
|
||||
// CoderMixer2.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __CODERMIXER2_H
|
||||
#define __CODERMIXER2_H
|
||||
#ifndef __CODER_MIXER2_H
|
||||
#define __CODER_MIXER2_H
|
||||
|
||||
#include "../../../Common/Vector.h"
|
||||
#include "../../../Common/Types.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Windows/Thread.h"
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
// #include "../../../Compress/Interface/CompressInterface.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
struct CBindPair
|
||||
{
|
||||
UINT32 InIndex;
|
||||
UINT32 OutIndex;
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
};
|
||||
|
||||
struct CCoderStreamsInfo
|
||||
{
|
||||
UINT32 NumInStreams;
|
||||
UINT32 NumOutStreams;
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
};
|
||||
|
||||
struct CBindInfo
|
||||
{
|
||||
CRecordVector<CCoderStreamsInfo> Coders;
|
||||
CRecordVector<CBindPair> BindPairs;
|
||||
CRecordVector<UINT32> InStreams;
|
||||
CRecordVector<UINT32> OutStreams;
|
||||
|
||||
UINT32 GetCoderStartOutStream(UINT32 coderIndex) const
|
||||
CRecordVector<UInt32> InStreams;
|
||||
CRecordVector<UInt32> OutStreams;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
UINT32 numOutStreams = 0;
|
||||
for (UINT32 i = 0; i < coderIndex; i++)
|
||||
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
|
||||
void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
|
||||
{
|
||||
numInStreams = 0;
|
||||
numOutStreams = 0;
|
||||
@@ -55,14 +60,14 @@ struct CBindInfo
|
||||
}
|
||||
}
|
||||
|
||||
int FindBinderForInStream(UINT32 inStream) const
|
||||
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
|
||||
int FindBinderForOutStream(UInt32 outStream) const
|
||||
{
|
||||
for (int i = 0; i < BindPairs.Size(); i++)
|
||||
if (BindPairs[i].OutIndex == outStream)
|
||||
@@ -70,29 +75,29 @@ struct CBindInfo
|
||||
return -1;
|
||||
}
|
||||
|
||||
UINT32 GetCoderInStreamIndex(UINT32 coderIndex) const
|
||||
UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
|
||||
{
|
||||
UINT32 streamIndex = 0;
|
||||
for (UINT32 i = 0; i < coderIndex; i++)
|
||||
UInt32 streamIndex = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
streamIndex += Coders[i].NumInStreams;
|
||||
return streamIndex;
|
||||
}
|
||||
|
||||
UINT32 GetCoderOutStreamIndex(UINT32 coderIndex) const
|
||||
UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
|
||||
{
|
||||
UINT32 streamIndex = 0;
|
||||
for (UINT32 i = 0; i < coderIndex; i++)
|
||||
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
|
||||
void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
|
||||
UInt32 &coderStreamIndex) const
|
||||
{
|
||||
for (coderIndex = 0; coderIndex < (UINT32)Coders.Size(); coderIndex++)
|
||||
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
|
||||
{
|
||||
UINT32 curSize = Coders[coderIndex].NumInStreams;
|
||||
UInt32 curSize = Coders[coderIndex].NumInStreams;
|
||||
if (streamIndex < curSize)
|
||||
{
|
||||
coderStreamIndex = streamIndex;
|
||||
@@ -102,12 +107,12 @@ struct CBindInfo
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
void FindOutStream(UINT32 streamIndex, UINT32 &coderIndex,
|
||||
UINT32 &coderStreamIndex) const
|
||||
void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
|
||||
UInt32 &coderStreamIndex) const
|
||||
{
|
||||
for (coderIndex = 0; coderIndex < (UINT32)Coders.Size(); coderIndex++)
|
||||
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
|
||||
{
|
||||
UINT32 curSize = Coders[coderIndex].NumOutStreams;
|
||||
UInt32 curSize = Coders[coderIndex].NumOutStreams;
|
||||
if (streamIndex < curSize)
|
||||
{
|
||||
coderStreamIndex = streamIndex;
|
||||
@@ -121,132 +126,41 @@ struct CBindInfo
|
||||
|
||||
class CBindReverseConverter
|
||||
{
|
||||
UINT32 _numSrcOutStreams;
|
||||
UInt32 _numSrcOutStreams;
|
||||
const NCoderMixer2::CBindInfo _srcBindInfo;
|
||||
CRecordVector<UINT32> _srcInToDestOutMap;
|
||||
CRecordVector<UINT32> _srcOutToDestInMap;
|
||||
CRecordVector<UINT32> _destInToSrcOutMap;
|
||||
CRecordVector<UInt32> _srcInToDestOutMap;
|
||||
CRecordVector<UInt32> _srcOutToDestInMap;
|
||||
CRecordVector<UInt32> _destInToSrcOutMap;
|
||||
public:
|
||||
UINT32 NumSrcInStreams;
|
||||
CRecordVector<UINT32> DestOutToSrcInMap;
|
||||
UInt32 NumSrcInStreams;
|
||||
CRecordVector<UInt32> DestOutToSrcInMap;
|
||||
|
||||
CBindReverseConverter(const NCoderMixer2::CBindInfo &srcBindInfo);
|
||||
void CreateReverseBindInfo(NCoderMixer2::CBindInfo &destBindInfo);
|
||||
};
|
||||
|
||||
// CreateEvents();
|
||||
// {
|
||||
// SetCoderInfo()
|
||||
// Init Streams
|
||||
// set CompressEvent()
|
||||
// wait CompressionCompletedEvent
|
||||
// }
|
||||
|
||||
struct CThreadCoderInfo2
|
||||
struct CCoderInfo
|
||||
{
|
||||
NWindows::NSynchronization::CAutoResetEvent *CompressEvent;
|
||||
HANDLE ExitEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent;
|
||||
|
||||
bool CompressorIsCoder2;
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
UINT32 NumInStreams;
|
||||
UINT32 NumOutStreams;
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
|
||||
CRecordVector<ISequentialInStream *> InStreamPointers;
|
||||
CRecordVector<ISequentialOutStream *> OutStreamPointers;
|
||||
CRecordVector<UINT64> InSizes;
|
||||
CRecordVector<UINT64> OutSizes;
|
||||
CRecordVector<const UINT64 *> InSizePointers;
|
||||
CRecordVector<const UINT64 *> OutSizePointers;
|
||||
CRecordVector<UInt64> InSizes;
|
||||
CRecordVector<UInt64> OutSizes;
|
||||
CRecordVector<const UInt64 *> InSizePointers;
|
||||
CRecordVector<const UInt64 *> OutSizePointers;
|
||||
|
||||
CMyComPtr<ICompressProgressInfo> Progress; // CMyComPtr
|
||||
HRESULT Result;
|
||||
|
||||
CThreadCoderInfo2(UINT32 numInStreams, UINT32 numOutStreams);
|
||||
void SetCoderInfo(const UINT64 **inSizes,
|
||||
const UINT64 **outSizes, ICompressProgressInfo *progress);
|
||||
~CThreadCoderInfo2();
|
||||
bool WaitAndCode();
|
||||
void CreateEvents();
|
||||
CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
|
||||
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
};
|
||||
|
||||
|
||||
// SetBindInfo()
|
||||
// for each coder
|
||||
// {
|
||||
// AddCoder[2]()
|
||||
// }
|
||||
//
|
||||
// for each file
|
||||
// {
|
||||
// ReInit()
|
||||
// for each coder
|
||||
// {
|
||||
// SetCoderInfo
|
||||
// }
|
||||
// SetProgressIndex(UINT32 coderIndex);
|
||||
// Code
|
||||
// }
|
||||
|
||||
|
||||
class CCoderMixer2:
|
||||
public ICompressCoder2,
|
||||
public CMyUnknownImp
|
||||
class CCoderMixer2
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
CCoderMixer2();
|
||||
~CCoderMixer2();
|
||||
void AddCoderCommon();
|
||||
void AddCoder(ICompressCoder *coder);
|
||||
void AddCoder2(ICompressCoder2 *coder);
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UINT32 coderIndex, const UINT64 **anInSize, const UINT64 **outSize)
|
||||
{ _coderInfoVector[coderIndex].SetCoderInfo(anInSize, outSize, NULL); }
|
||||
void SetProgressCoderIndex(UINT32 coderIndex)
|
||||
{ _progressCoderIndex = coderIndex; }
|
||||
|
||||
|
||||
UINT64 GetWriteProcessedSize(UINT32 binderIndex) const;
|
||||
|
||||
|
||||
bool MyCode();
|
||||
|
||||
private:
|
||||
CBindInfo _bindInfo;
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
CObjectVector<CThreadCoderInfo2> _coderInfoVector;
|
||||
CRecordVector<HANDLE> _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);
|
||||
|
||||
virtual void SetBindInfo(const CBindInfo &bindInfo) = 0;
|
||||
virtual void ReInit() = 0;
|
||||
virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
360
7zip/Archive/Common/CoderMixer2MT.cpp
Executable file
360
7zip/Archive/Common/CoderMixer2MT.cpp
Executable file
@@ -0,0 +1,360 @@
|
||||
// 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)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// CCoderMixer2MT
|
||||
|
||||
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
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;
|
||||
UInt32 numInStreams = 0, numOutStreams = 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();
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
121
7zip/Archive/Common/CoderMixer2MT.h
Executable file
121
7zip/Archive/Common/CoderMixer2MT.h
Executable file
@@ -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
|
||||
|
||||
238
7zip/Archive/Common/CoderMixer2ST.cpp
Executable file
238
7zip/Archive/Common/CoderMixer2ST.cpp
Executable file
@@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
87
7zip/Archive/Common/CoderMixer2ST.h
Executable file
87
7zip/Archive/Common/CoderMixer2ST.h
Executable file
@@ -0,0 +1,87 @@
|
||||
// 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
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// CodersPath.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('\\'));
|
||||
return path.Left(pos + 1);
|
||||
}
|
||||
|
||||
CSysString GetBaseFolderPrefix()
|
||||
{
|
||||
CSysString libPrefix = GetLibraryFolderPrefix();
|
||||
CSysString temp = libPrefix;
|
||||
temp.Delete(temp.Length() - 1);
|
||||
int pos = temp.ReverseFind(TEXT('\\'));
|
||||
return temp.Left(pos + 1);
|
||||
}
|
||||
|
||||
CSysString GetCodecsFolderPrefix()
|
||||
{
|
||||
return GetBaseFolderPrefix() + TEXT("Compress\\");
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "CrossThreadProgress.h"
|
||||
|
||||
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UINT64 *inSize, const UINT64 *outSize)
|
||||
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
InSize = inSize;
|
||||
OutSize = outSize;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// CrossThreadProgress.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __CROSSTHREADPROGRESS_H
|
||||
#define __CROSSTHREADPROGRESS_H
|
||||
|
||||
@@ -14,8 +12,8 @@ class CCrossThreadProgress:
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
const UINT64 *InSize;
|
||||
const UINT64 *OutSize;
|
||||
const UInt64 *InSize;
|
||||
const UInt64 *OutSize;
|
||||
HRESULT Result;
|
||||
NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent WaitEvent;
|
||||
@@ -27,7 +25,7 @@ public:
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UINT64 *inSize, const UINT64 *outSize);
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,7 @@ void CDummyOutStream::Init(ISequentialOutStream *outStream)
|
||||
}
|
||||
|
||||
STDMETHODIMP CDummyOutStream::Write(const void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(m_Stream)
|
||||
return m_Stream->Write(data, size, processedSize);
|
||||
@@ -20,7 +20,7 @@ STDMETHODIMP CDummyOutStream::Write(const void *data,
|
||||
}
|
||||
|
||||
STDMETHODIMP CDummyOutStream::WritePart(const void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(m_Stream)
|
||||
return m_Stream->WritePart(data, size, processedSize);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// DummyOutStream.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __DUMMYOUTSTREAM_H
|
||||
#define __DUMMYOUTSTREAM_H
|
||||
|
||||
@@ -15,8 +13,8 @@ class CDummyOutStream:
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialOutStream> m_Stream;
|
||||
public:
|
||||
|
||||
244
7zip/Archive/Common/FilterCoder.cpp
Executable file
244
7zip/Archive/Common/FilterCoder.cpp
Executable file
@@ -0,0 +1,244 @@
|
||||
// FilterCoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "FilterCoder.h"
|
||||
#include "../../../Common/Alloc.h"
|
||||
#include "../../../Common/Defs.h"
|
||||
|
||||
static const int kBufferSize = 1 << 17;
|
||||
|
||||
CFilterCoder::CFilterCoder()
|
||||
{
|
||||
_buffer = (Byte *)::BigAlloc(kBufferSize);
|
||||
}
|
||||
|
||||
CFilterCoder::~CFilterCoder()
|
||||
{
|
||||
BigFree(_buffer);
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
|
||||
{
|
||||
if (_outSizeIsDefined)
|
||||
{
|
||||
UInt64 remSize = _outSize - _nowPos64;
|
||||
if (size > remSize)
|
||||
size = (UInt32)remSize;
|
||||
}
|
||||
UInt32 processedSize = 0;
|
||||
RINOK(outStream->Write(_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)
|
||||
{
|
||||
Init();
|
||||
UInt32 bufferPos = 0;
|
||||
if (_outSizeIsDefined = (outSize != 0))
|
||||
_outSize = *outSize;
|
||||
|
||||
while(NeedMore())
|
||||
{
|
||||
UInt32 processedSize;
|
||||
UInt32 size = kBufferSize - bufferPos;
|
||||
RINOK(inStream->Read(_buffer + bufferPos, size, &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;
|
||||
Init();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
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(_outStream->Write(_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;
|
||||
Init();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
RINOK(_inStream->Read(_buffer + _bufferPos, size0, &processedSizeTemp));
|
||||
_bufferPos = _bufferPos + processedSizeTemp;
|
||||
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
||||
if (_convertedPosEnd == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (_convertedPosEnd > _bufferPos)
|
||||
{
|
||||
for (; _bufferPos < _convertedPosEnd; _bufferPos++)
|
||||
_buffer[_bufferPos] = 0;
|
||||
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
||||
}
|
||||
}
|
||||
if (processedSize != NULL)
|
||||
*processedSize = processedSizeTotal;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
// #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);
|
||||
}
|
||||
132
7zip/Archive/Common/FilterCoder.h
Executable file
132
7zip/Archive/Common/FilterCoder.h
Executable file
@@ -0,0 +1,132 @@
|
||||
// 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;
|
||||
|
||||
void Init()
|
||||
{
|
||||
Filter->Init();
|
||||
_nowPos64 = 0;
|
||||
_outSizeIsDefined = false;
|
||||
}
|
||||
|
||||
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(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); \
|
||||
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(ReleaseOutStream)();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(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
|
||||
@@ -4,10 +4,34 @@
|
||||
|
||||
#include "InStreamWithCRC.h"
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Read(void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialInStreamWithCRC::ReadPart(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
_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);
|
||||
_size += realProcessedSize;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
@@ -17,9 +41,9 @@ STDMETHODIMP CInStreamWithCRC::Read(void *data,
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::ReadPart(void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
@@ -28,8 +52,8 @@ STDMETHODIMP CInStreamWithCRC::ReadPart(void *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Seek(INT64 offset,
|
||||
UINT32 seekOrigin, UINT64 *newPosition)
|
||||
STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset,
|
||||
UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (seekOrigin != STREAM_SEEK_SET || offset != 0)
|
||||
return E_FAIL;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// InStreamWithCRC.h
|
||||
|
||||
// #pragma once
|
||||
|
||||
#ifndef __INSTREAMWITHCRC_H
|
||||
#define __INSTREAMWITHCRC_H
|
||||
|
||||
@@ -9,6 +7,31 @@
|
||||
#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);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
public:
|
||||
void Init(ISequentialInStream *stream)
|
||||
{
|
||||
_stream = stream;
|
||||
_size = 0;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
class CInStreamWithCRC:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
@@ -16,12 +39,12 @@ class CInStreamWithCRC:
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(Seek)(INT64 offset, UINT32 seekOrigin, UINT64 *newPosition);
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
private:
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UINT64 _size;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
public:
|
||||
void Init(IInStream *stream)
|
||||
@@ -31,8 +54,8 @@ public:
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UINT32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UINT64 GetSize() const { return _size; }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,28 +10,41 @@ namespace NItemName {
|
||||
static const wchar_t kOSDirDelimiter = '\\';
|
||||
static const wchar_t kDirDelimiter = '/';
|
||||
|
||||
UString MakeLegalName(const UString &aName)
|
||||
UString MakeLegalName(const UString &name)
|
||||
{
|
||||
UString aZipName = aName;
|
||||
aZipName.Replace(kOSDirDelimiter, kDirDelimiter);
|
||||
return aZipName;
|
||||
UString zipName = name;
|
||||
zipName.Replace(kOSDirDelimiter, kDirDelimiter);
|
||||
return zipName;
|
||||
}
|
||||
|
||||
UString GetOSName(const UString &aName)
|
||||
UString GetOSName(const UString &name)
|
||||
{
|
||||
UString aNewName = aName;
|
||||
aNewName.Replace(kDirDelimiter, kOSDirDelimiter);
|
||||
return aNewName;
|
||||
UString newName = name;
|
||||
newName.Replace(kDirDelimiter, kOSDirDelimiter);
|
||||
return newName;
|
||||
}
|
||||
|
||||
UString GetOSName2(const UString &aName)
|
||||
UString GetOSName2(const UString &name)
|
||||
{
|
||||
if (aName.IsEmpty())
|
||||
if (name.IsEmpty())
|
||||
return UString();
|
||||
UString aNewName = GetOSName(aName);
|
||||
if (aNewName[aNewName.Length() - 1] == kOSDirDelimiter)
|
||||
aNewName.Delete(aNewName.Length() - 1);
|
||||
return aNewName;
|
||||
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(codePage, name, &name[name.Length()], 0);
|
||||
#else
|
||||
(LPCSTR)(name) + (name.Length() - 1);
|
||||
#endif
|
||||
return (*prev == '/');
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// Archive/Common/ItemNameUtils.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_ITEMNAMEUTILS_H
|
||||
#define __ARCHIVE_ITEMNAMEUTILS_H
|
||||
|
||||
@@ -10,9 +8,10 @@
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
UString MakeLegalName(const UString &aName);
|
||||
UString GetOSName(const UString &aName);
|
||||
UString GetOSName2(const UString &aName);
|
||||
UString MakeLegalName(const UString &name);
|
||||
UString GetOSName(const UString &name);
|
||||
UString GetOSName2(const UString &name);
|
||||
bool HasTailSlash(const AString &name, UINT codePage);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
213
7zip/Archive/Common/MultiStream.cpp
Executable file
213
7zip/Archive/Common/MultiStream.cpp
Executable file
@@ -0,0 +1,213 @@
|
||||
// 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);
|
||||
if (realProcessed == 0)
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMultiStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
UInt64 *newPosition)
|
||||
{
|
||||
UInt64 newPos;
|
||||
if(seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
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;
|
||||
}
|
||||
_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);
|
||||
STDMETHOD(WritePart)(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)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
*/
|
||||
78
7zip/Archive/Common/MultiStream.h
Executable file
78
7zip/Archive/Common/MultiStream.h
Executable file
@@ -0,0 +1,78 @@
|
||||
// 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(ReadPart)(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(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -5,10 +5,10 @@
|
||||
#include "OutStreamWithCRC.h"
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT result;
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
@@ -23,9 +23,9 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
}
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::WritePart(const void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// OutStreamWithCRC.h
|
||||
|
||||
// #pragma once
|
||||
|
||||
#ifndef __OUTSTREAMWITHCRC_H
|
||||
#define __OUTSTREAMWITHCRC_H
|
||||
|
||||
@@ -16,8 +14,8 @@ class COutStreamWithCRC:
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CCRC _crc;
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
@@ -28,7 +26,7 @@ public:
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UINT32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
void InitCRC() { _crc.Init(); }
|
||||
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// stdafx.h
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user