mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 11:14:58 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
34
CPP/7zip/Archive/Common/CodecsPath.cpp
Executable file
34
CPP/7zip/Archive/Common/CodecsPath.cpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// CodecsPath.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "../../../Common/String.h"
|
||||
|
||||
extern HINSTANCE g_hInstance;
|
||||
|
||||
static CSysString GetLibraryPath()
|
||||
{
|
||||
TCHAR fullPath[MAX_PATH + 1];
|
||||
::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
static CSysString GetLibraryFolderPrefix()
|
||||
{
|
||||
CSysString path = GetLibraryPath();
|
||||
int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
|
||||
return path.Left(pos + 1);
|
||||
}
|
||||
|
||||
CSysString GetBaseFolderPrefix()
|
||||
{
|
||||
CSysString libPrefix = GetLibraryFolderPrefix();
|
||||
CSysString temp = libPrefix;
|
||||
temp.Delete(temp.Length() - 1);
|
||||
int pos = temp.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
|
||||
return temp.Left(pos + 1);
|
||||
}
|
||||
|
||||
CSysString GetCodecsFolderPrefix()
|
||||
{
|
||||
return GetBaseFolderPrefix() + (CSysString)(TEXT("Codecs")) + (CSysString)(TEXT(STRING_PATH_SEPARATOR));
|
||||
}
|
||||
12
CPP/7zip/Archive/Common/CodecsPath.h
Executable file
12
CPP/7zip/Archive/Common/CodecsPath.h
Executable file
@@ -0,0 +1,12 @@
|
||||
// CodecsPath.h
|
||||
|
||||
#ifndef __CODECSPATH_H
|
||||
#define __CODECSPATH_H
|
||||
|
||||
#include "../../../Common/String.h"
|
||||
|
||||
CSysString GetBaseFolderPrefix();
|
||||
CSysString GetCodecsFolderPrefix();
|
||||
|
||||
#endif
|
||||
|
||||
31
CPP/7zip/Archive/Common/CoderLoader.cpp
Executable file
31
CPP/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;
|
||||
}
|
||||
147
CPP/7zip/Archive/Common/CoderLoader.h
Executable file
147
CPP/7zip/Archive/Common/CoderLoader.h
Executable file
@@ -0,0 +1,147 @@
|
||||
// CoderLoader.h
|
||||
|
||||
#ifndef __CODERLOADER_H
|
||||
#define __CODERLOADER_H
|
||||
|
||||
#include "../../../Common/String.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Windows/DLL.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
typedef UInt32 (WINAPI * CreateObjectPointer)(
|
||||
const GUID *clsID,
|
||||
const GUID *interfaceID,
|
||||
void **outObject);
|
||||
|
||||
class CCoderLibrary: public NWindows::NDLL::CLibrary
|
||||
{
|
||||
public:
|
||||
HRESULT CreateObject(REFGUID clsID, REFGUID iid, void **obj)
|
||||
{
|
||||
CreateObjectPointer createObject = (CreateObjectPointer)
|
||||
GetProcAddress("CreateObject");
|
||||
if (createObject == NULL)
|
||||
return GetLastError();
|
||||
return createObject(&clsID, &iid, obj);
|
||||
}
|
||||
|
||||
HRESULT CreateFilter(REFGUID clsID, ICompressFilter **filter)
|
||||
{
|
||||
return CreateObject(clsID, IID_ICompressFilter, (void **)filter);
|
||||
}
|
||||
|
||||
HRESULT CreateCoder(REFGUID clsID, ICompressCoder **coder)
|
||||
{
|
||||
return CreateObject(clsID, IID_ICompressCoder, (void **)coder);
|
||||
}
|
||||
|
||||
HRESULT CreateCoderSpec(REFGUID clsID, ICompressCoder **coder);
|
||||
|
||||
HRESULT LoadAndCreateFilter(LPCTSTR filePath, REFGUID clsID, ICompressFilter **filter)
|
||||
{
|
||||
CCoderLibrary libTemp;
|
||||
if (!libTemp.Load(filePath))
|
||||
return GetLastError();
|
||||
RINOK(libTemp.CreateFilter(clsID, filter));
|
||||
Attach(libTemp.Detach());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT LoadAndCreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
|
||||
{
|
||||
CCoderLibrary libTemp;
|
||||
if (!libTemp.Load(filePath))
|
||||
return GetLastError();
|
||||
RINOK(libTemp.CreateCoder(clsID, coder));
|
||||
Attach(libTemp.Detach());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder);
|
||||
HRESULT CreateCoder2(REFGUID clsID, ICompressCoder2 **coder)
|
||||
{
|
||||
CreateObjectPointer createObject = (CreateObjectPointer)
|
||||
GetProcAddress("CreateObject");
|
||||
if (createObject == NULL)
|
||||
return GetLastError();
|
||||
return createObject(&clsID, &IID_ICompressCoder2, (void **)coder);
|
||||
}
|
||||
HRESULT LoadAndCreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder)
|
||||
{
|
||||
CCoderLibrary libTemp;
|
||||
if (!libTemp.Load(filePath))
|
||||
return GetLastError();
|
||||
RINOK(libTemp.CreateCoder2(clsID, coder));
|
||||
Attach(libTemp.Detach());
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CCoderLibraries
|
||||
{
|
||||
struct CPathToLibraryPair
|
||||
{
|
||||
CSysString Path;
|
||||
CCoderLibrary Libary;
|
||||
};
|
||||
CObjectVector<CPathToLibraryPair> Pairs;
|
||||
public:
|
||||
int FindPath(LPCTSTR filePath)
|
||||
{
|
||||
for (int i = 0; i < Pairs.Size(); i++)
|
||||
if (Pairs[i].Path.CompareNoCase(filePath) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
HRESULT CreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
|
||||
{
|
||||
int index = FindPath(filePath);
|
||||
if (index < 0)
|
||||
{
|
||||
CPathToLibraryPair pair;
|
||||
RINOK(pair.Libary.LoadAndCreateCoder(filePath, clsID, coder));
|
||||
pair.Path = filePath;
|
||||
Pairs.Add(pair);
|
||||
pair.Libary.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
return Pairs[index].Libary.CreateCoder(clsID, coder);
|
||||
}
|
||||
|
||||
HRESULT CreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
|
||||
{
|
||||
int index = FindPath(filePath);
|
||||
if (index < 0)
|
||||
{
|
||||
CPathToLibraryPair pair;
|
||||
RINOK(pair.Libary.LoadAndCreateCoderSpec(filePath, clsID, coder));
|
||||
pair.Path = filePath;
|
||||
Pairs.Add(pair);
|
||||
pair.Libary.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
return Pairs[index].Libary.CreateCoderSpec(clsID, coder);
|
||||
}
|
||||
|
||||
HRESULT CreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder)
|
||||
{
|
||||
int index = FindPath(filePath);
|
||||
if (index < 0)
|
||||
{
|
||||
CPathToLibraryPair pair;
|
||||
RINOK(pair.Libary.LoadAndCreateCoder2(filePath, clsID, coder));
|
||||
pair.Path = filePath;
|
||||
Pairs.Add(pair);
|
||||
pair.Libary.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
return Pairs[index].Libary.CreateCoder2(clsID, coder);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
121
CPP/7zip/Archive/Common/CoderMixer2.cpp
Executable file
121
CPP/7zip/Archive/Common/CoderMixer2.cpp
Executable file
@@ -0,0 +1,121 @@
|
||||
// CoderMixer2.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
_srcBindInfo(srcBindInfo)
|
||||
{
|
||||
srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
|
||||
|
||||
UInt32 j;
|
||||
for (j = 0; j < NumSrcInStreams; j++)
|
||||
{
|
||||
_srcInToDestOutMap.Add(0);
|
||||
DestOutToSrcInMap.Add(0);
|
||||
}
|
||||
for (j = 0; j < _numSrcOutStreams; j++)
|
||||
{
|
||||
_srcOutToDestInMap.Add(0);
|
||||
_destInToSrcOutMap.Add(0);
|
||||
}
|
||||
|
||||
UInt32 destInOffset = 0;
|
||||
UInt32 destOutOffset = 0;
|
||||
UInt32 srcInOffset = NumSrcInStreams;
|
||||
UInt32 srcOutOffset = _numSrcOutStreams;
|
||||
|
||||
for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];
|
||||
|
||||
srcInOffset -= srcCoderInfo.NumInStreams;
|
||||
srcOutOffset -= srcCoderInfo.NumOutStreams;
|
||||
|
||||
UInt32 j;
|
||||
for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
|
||||
{
|
||||
UInt32 index = srcInOffset + j;
|
||||
_srcInToDestOutMap[index] = destOutOffset;
|
||||
DestOutToSrcInMap[destOutOffset] = index;
|
||||
}
|
||||
for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
|
||||
{
|
||||
UInt32 index = srcOutOffset + j;
|
||||
_srcOutToDestInMap[index] = destInOffset;
|
||||
_destInToSrcOutMap[destInOffset] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
|
||||
{
|
||||
destBindInfo.Coders.Clear();
|
||||
destBindInfo.BindPairs.Clear();
|
||||
destBindInfo.InStreams.Clear();
|
||||
destBindInfo.OutStreams.Clear();
|
||||
|
||||
int i;
|
||||
for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
|
||||
CCoderStreamsInfo destCoderInfo;
|
||||
destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
|
||||
destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
|
||||
destBindInfo.Coders.Add(destCoderInfo);
|
||||
}
|
||||
for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
|
||||
CBindPair destBindPair;
|
||||
destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
|
||||
destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
|
||||
destBindInfo.BindPairs.Add(destBindPair);
|
||||
}
|
||||
for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
|
||||
destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
|
||||
for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
|
||||
destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
|
||||
}
|
||||
|
||||
CCoderInfo::CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
NumInStreams(numInStreams),
|
||||
NumOutStreams(numOutStreams)
|
||||
{
|
||||
InSizes.Reserve(NumInStreams);
|
||||
InSizePointers.Reserve(NumInStreams);
|
||||
OutSizePointers.Reserve(NumOutStreams);
|
||||
OutSizePointers.Reserve(NumOutStreams);
|
||||
}
|
||||
|
||||
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
|
||||
{
|
||||
sizes.Clear();
|
||||
sizePointers.Clear();
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (srcSizes == 0 || srcSizes[i] == NULL)
|
||||
{
|
||||
sizes.Add(0);
|
||||
sizePointers.Add(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes.Add(*srcSizes[i]);
|
||||
sizePointers.Add(&sizes.Back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderInfo::SetCoderInfo(const UInt64 **inSizes,
|
||||
const UInt64 **outSizes)
|
||||
{
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
}
|
||||
|
||||
}
|
||||
168
CPP/7zip/Archive/Common/CoderMixer2.h
Executable file
168
CPP/7zip/Archive/Common/CoderMixer2.h
Executable file
@@ -0,0 +1,168 @@
|
||||
// CoderMixer2.h
|
||||
|
||||
#ifndef __CODER_MIXER2_H
|
||||
#define __CODER_MIXER2_H
|
||||
|
||||
#include "../../../Common/Vector.h"
|
||||
#include "../../../Common/Types.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
struct CBindPair
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
};
|
||||
|
||||
struct CCoderStreamsInfo
|
||||
{
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
};
|
||||
|
||||
struct CBindInfo
|
||||
{
|
||||
CRecordVector<CCoderStreamsInfo> Coders;
|
||||
CRecordVector<CBindPair> BindPairs;
|
||||
CRecordVector<UInt32> InStreams;
|
||||
CRecordVector<UInt32> OutStreams;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Coders.Clear();
|
||||
BindPairs.Clear();
|
||||
InStreams.Clear();
|
||||
OutStreams.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 numOutStreams = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
numOutStreams += Coders[i].NumOutStreams;
|
||||
return numOutStreams;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
|
||||
{
|
||||
numInStreams = 0;
|
||||
numOutStreams = 0;
|
||||
for (int i = 0; i < Coders.Size(); i++)
|
||||
{
|
||||
const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
|
||||
numInStreams += coderStreamsInfo.NumInStreams;
|
||||
numOutStreams += coderStreamsInfo.NumOutStreams;
|
||||
}
|
||||
}
|
||||
|
||||
int FindBinderForInStream(UInt32 inStream) const
|
||||
{
|
||||
for (int i = 0; i < BindPairs.Size(); i++)
|
||||
if (BindPairs[i].InIndex == inStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindBinderForOutStream(UInt32 outStream) const
|
||||
{
|
||||
for (int i = 0; i < BindPairs.Size(); i++)
|
||||
if (BindPairs[i].OutIndex == outStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 streamIndex = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
streamIndex += Coders[i].NumInStreams;
|
||||
return streamIndex;
|
||||
}
|
||||
|
||||
UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 streamIndex = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
streamIndex += Coders[i].NumOutStreams;
|
||||
return streamIndex;
|
||||
}
|
||||
|
||||
|
||||
void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
|
||||
UInt32 &coderStreamIndex) const
|
||||
{
|
||||
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
|
||||
{
|
||||
UInt32 curSize = Coders[coderIndex].NumInStreams;
|
||||
if (streamIndex < curSize)
|
||||
{
|
||||
coderStreamIndex = streamIndex;
|
||||
return;
|
||||
}
|
||||
streamIndex -= curSize;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
|
||||
UInt32 &coderStreamIndex) const
|
||||
{
|
||||
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
|
||||
{
|
||||
UInt32 curSize = Coders[coderIndex].NumOutStreams;
|
||||
if (streamIndex < curSize)
|
||||
{
|
||||
coderStreamIndex = streamIndex;
|
||||
return;
|
||||
}
|
||||
streamIndex -= curSize;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
};
|
||||
|
||||
class CBindReverseConverter
|
||||
{
|
||||
UInt32 _numSrcOutStreams;
|
||||
NCoderMixer2::CBindInfo _srcBindInfo;
|
||||
CRecordVector<UInt32> _srcInToDestOutMap;
|
||||
CRecordVector<UInt32> _srcOutToDestInMap;
|
||||
CRecordVector<UInt32> _destInToSrcOutMap;
|
||||
public:
|
||||
UInt32 NumSrcInStreams;
|
||||
CRecordVector<UInt32> DestOutToSrcInMap;
|
||||
|
||||
CBindReverseConverter(const NCoderMixer2::CBindInfo &srcBindInfo);
|
||||
void CreateReverseBindInfo(NCoderMixer2::CBindInfo &destBindInfo);
|
||||
};
|
||||
|
||||
struct CCoderInfo
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
|
||||
CRecordVector<UInt64> InSizes;
|
||||
CRecordVector<UInt64> OutSizes;
|
||||
CRecordVector<const UInt64 *> InSizePointers;
|
||||
CRecordVector<const UInt64 *> OutSizePointers;
|
||||
|
||||
CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
|
||||
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
};
|
||||
|
||||
class CCoderMixer2
|
||||
{
|
||||
public:
|
||||
virtual void SetBindInfo(const CBindInfo &bindInfo) = 0;
|
||||
virtual void ReInit() = 0;
|
||||
virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
359
CPP/7zip/Archive/Common/CoderMixer2MT.cpp
Executable file
359
CPP/7zip/Archive/Common/CoderMixer2MT.cpp
Executable file
@@ -0,0 +1,359 @@
|
||||
// CoderMixer2MT.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer2MT.h"
|
||||
#include "CrossThreadProgress.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NSynchronization;
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
CThreadCoderInfo::CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
ExitEvent(NULL),
|
||||
CompressEvent(NULL),
|
||||
CompressionCompletedEvent(NULL),
|
||||
CCoderInfo(numInStreams, numOutStreams)
|
||||
{
|
||||
InStreams.Reserve(NumInStreams);
|
||||
InStreamPointers.Reserve(NumInStreams);
|
||||
OutStreams.Reserve(NumOutStreams);
|
||||
OutStreamPointers.Reserve(NumOutStreams);
|
||||
}
|
||||
|
||||
void CThreadCoderInfo::CreateEvents()
|
||||
{
|
||||
CompressEvent = new CAutoResetEvent(false);
|
||||
CompressionCompletedEvent = new CAutoResetEvent(false);
|
||||
}
|
||||
|
||||
CThreadCoderInfo::~CThreadCoderInfo()
|
||||
{
|
||||
if (CompressEvent != NULL)
|
||||
delete CompressEvent;
|
||||
if (CompressionCompletedEvent != NULL)
|
||||
delete CompressionCompletedEvent;
|
||||
}
|
||||
|
||||
class CCoderInfoFlusher2
|
||||
{
|
||||
CThreadCoderInfo *m_CoderInfo;
|
||||
public:
|
||||
CCoderInfoFlusher2(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {}
|
||||
~CCoderInfoFlusher2()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m_CoderInfo->InStreams.Size(); i++)
|
||||
m_CoderInfo->InStreams[i].Release();
|
||||
for (i = 0; i < m_CoderInfo->OutStreams.Size(); i++)
|
||||
m_CoderInfo->OutStreams[i].Release();
|
||||
m_CoderInfo->CompressionCompletedEvent->Set();
|
||||
}
|
||||
};
|
||||
|
||||
bool CThreadCoderInfo::WaitAndCode()
|
||||
{
|
||||
HANDLE events[2] = { ExitEvent, *CompressEvent };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
if (waitResult == WAIT_OBJECT_0 + 0)
|
||||
return false;
|
||||
|
||||
{
|
||||
InStreamPointers.Clear();
|
||||
OutStreamPointers.Clear();
|
||||
UInt32 i;
|
||||
for (i = 0; i < NumInStreams; i++)
|
||||
{
|
||||
if (InSizePointers[i] != NULL)
|
||||
InSizePointers[i] = &InSizes[i];
|
||||
InStreamPointers.Add(InStreams[i]);
|
||||
}
|
||||
for (i = 0; i < NumOutStreams; i++)
|
||||
{
|
||||
if (OutSizePointers[i] != NULL)
|
||||
OutSizePointers[i] = &OutSizes[i];
|
||||
OutStreamPointers.Add(OutStreams[i]);
|
||||
}
|
||||
CCoderInfoFlusher2 coderInfoFlusher(this);
|
||||
if (Coder)
|
||||
Result = Coder->Code(InStreamPointers[0],
|
||||
OutStreamPointers[0],
|
||||
InSizePointers[0],
|
||||
OutSizePointers[0],
|
||||
Progress);
|
||||
else
|
||||
Result = Coder2->Code(&InStreamPointers.Front(),
|
||||
&InSizePointers.Front(),
|
||||
NumInStreams,
|
||||
&OutStreamPointers.Front(),
|
||||
&OutSizePointers.Front(),
|
||||
NumOutStreams,
|
||||
Progress);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
|
||||
{
|
||||
sizes.Clear();
|
||||
sizePointers.Clear();
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (srcSizes == 0 || srcSizes[i] == NULL)
|
||||
{
|
||||
sizes.Add(0);
|
||||
sizePointers.Add(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes.Add(*srcSizes[i]);
|
||||
sizePointers.Add(&sizes.Back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CThreadCoderInfo::SetCoderInfo(const UInt64 **inSizes,
|
||||
const UInt64 **outSizes, ICompressProgressInfo *progress)
|
||||
{
|
||||
Progress = progress;
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
}
|
||||
|
||||
static DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// CCoderMixer2MT
|
||||
|
||||
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (!((CCoderMixer2MT *)threadCoderInfo)->MyCode())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CCoderMixer2MT::CCoderMixer2MT()
|
||||
{
|
||||
if (!_mainThread.Create(MainCoderThread, this))
|
||||
throw 271825;
|
||||
}
|
||||
|
||||
CCoderMixer2MT::~CCoderMixer2MT()
|
||||
{
|
||||
_exitEvent.Set();
|
||||
_mainThread.Wait();
|
||||
for(int i = 0; i < _threads.Size(); i++)
|
||||
{
|
||||
_threads[i].Wait();
|
||||
_threads[i].Close();
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
_bindInfo = bindInfo;
|
||||
_streamBinders.Clear();
|
||||
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
|
||||
{
|
||||
_streamBinders.Add(CStreamBinder());
|
||||
_streamBinders.Back().CreateEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoderCommon()
|
||||
{
|
||||
int index = _coderInfoVector.Size();
|
||||
const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index];
|
||||
|
||||
CThreadCoderInfo threadCoderInfo(CoderStreamsInfo.NumInStreams,
|
||||
CoderStreamsInfo.NumOutStreams);
|
||||
_coderInfoVector.Add(threadCoderInfo);
|
||||
_coderInfoVector.Back().CreateEvents();
|
||||
_coderInfoVector.Back().ExitEvent = _exitEvent;
|
||||
_compressingCompletedEvents.Add(*_coderInfoVector.Back().CompressionCompletedEvent);
|
||||
|
||||
NWindows::CThread newThread;
|
||||
_threads.Add(newThread);
|
||||
if (!_threads.Back().Create(CoderThread, &_coderInfoVector.Back()))
|
||||
throw 271824;
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coderInfoVector.Back().Coder = coder;
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coderInfoVector.Back().Coder2 = coder;
|
||||
}
|
||||
|
||||
/*
|
||||
void CCoderMixer2MT::FinishAddingCoders()
|
||||
{
|
||||
for(int i = 0; i < _coderInfoVector.Size(); i++)
|
||||
{
|
||||
DWORD id;
|
||||
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
|
||||
&_coderInfoVector[i], 0, &id);
|
||||
if (newThread == 0)
|
||||
throw 271824;
|
||||
_threads.Add(newThread);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void CCoderMixer2MT::ReInit()
|
||||
{
|
||||
for(int i = 0; i < _streamBinders.Size(); i++)
|
||||
_streamBinders[i].ReInit();
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2MT::Init(ISequentialInStream **inStreams,
|
||||
ISequentialOutStream **outStreams)
|
||||
{
|
||||
if (_coderInfoVector.Size() != _bindInfo.Coders.Size())
|
||||
throw 0;
|
||||
int i;
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
{
|
||||
CThreadCoderInfo &coderInfo = _coderInfoVector[i];
|
||||
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
|
||||
coderInfo.InStreams.Clear();
|
||||
UInt32 j;
|
||||
for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
|
||||
coderInfo.InStreams.Add(NULL);
|
||||
coderInfo.OutStreams.Clear();
|
||||
for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
|
||||
coderInfo.OutStreams.Add(NULL);
|
||||
}
|
||||
|
||||
for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
|
||||
{
|
||||
const CBindPair &bindPair = _bindInfo.BindPairs[i];
|
||||
UInt32 inCoderIndex, inCoderStreamIndex;
|
||||
UInt32 outCoderIndex, outCoderStreamIndex;
|
||||
_bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
|
||||
_bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
|
||||
|
||||
_streamBinders[i].CreateStreams(
|
||||
&_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
&_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex]);
|
||||
}
|
||||
|
||||
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
|
||||
{
|
||||
UInt32 inCoderIndex, inCoderStreamIndex;
|
||||
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
|
||||
_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
|
||||
}
|
||||
|
||||
for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
|
||||
{
|
||||
UInt32 outCoderIndex, outCoderStreamIndex;
|
||||
_bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
|
||||
_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
bool CCoderMixer2MT::MyCode()
|
||||
{
|
||||
HANDLE events[2] = { _exitEvent, _startCompressingEvent };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
if (waitResult == WAIT_OBJECT_0 + 0)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < _coderInfoVector.Size(); i++)
|
||||
_coderInfoVector[i].CompressEvent->Set();
|
||||
/* DWORD result = */ ::WaitForMultipleObjects(_compressingCompletedEvents.Size(),
|
||||
&_compressingCompletedEvents.Front(), TRUE, INFINITE);
|
||||
|
||||
_compressingFinishedEvent.Set();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
const UInt64 ** /* inSizes */,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 ** /* outSizes */,
|
||||
UInt32 numOutStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
|
||||
numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
|
||||
return E_INVALIDARG;
|
||||
|
||||
Init(inStreams, outStreams);
|
||||
|
||||
_compressingFinishedEvent.Reset(); // ?
|
||||
|
||||
CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
|
||||
CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
|
||||
progressSpec->Init();
|
||||
_coderInfoVector[_progressCoderIndex].Progress = crossProgress;
|
||||
|
||||
_startCompressingEvent.Set();
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
HANDLE events[2] = {_compressingFinishedEvent, progressSpec->ProgressEvent };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
if (waitResult == WAIT_OBJECT_0 + 0)
|
||||
break;
|
||||
if (progress != NULL)
|
||||
progressSpec->Result = progress->SetRatioInfo(progressSpec->InSize,
|
||||
progressSpec->OutSize);
|
||||
else
|
||||
progressSpec->Result = S_OK;
|
||||
progressSpec->WaitEvent.Set();
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coderInfoVector[i].Result;
|
||||
if (result == S_FALSE)
|
||||
return result;
|
||||
}
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coderInfoVector[i].Result;
|
||||
if (result != S_OK && result != E_FAIL)
|
||||
return result;
|
||||
}
|
||||
for(i = 0; i < _coderInfoVector.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coderInfoVector[i].Result;
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UInt64 CCoderMixer2MT::GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
{
|
||||
return _streamBinders[binderIndex].ProcessedSize;
|
||||
}
|
||||
|
||||
}
|
||||
121
CPP/7zip/Archive/Common/CoderMixer2MT.h
Executable file
121
CPP/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
CPP/7zip/Archive/Common/CoderMixer2ST.cpp
Executable file
238
CPP/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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
88
CPP/7zip/Archive/Common/CoderMixer2ST.h
Executable file
88
CPP/7zip/Archive/Common/CoderMixer2ST.h
Executable file
@@ -0,0 +1,88 @@
|
||||
// CoderMixer2ST.h
|
||||
|
||||
#ifndef __CODER_MIXER2_ST_H
|
||||
#define __CODER_MIXER2_ST_H
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
// SetBindInfo()
|
||||
// for each coder
|
||||
// {
|
||||
// AddCoder[2]()
|
||||
// }
|
||||
//
|
||||
// for each file
|
||||
// {
|
||||
// ReInit()
|
||||
// for each coder
|
||||
// {
|
||||
// SetCoderInfo
|
||||
// }
|
||||
// SetProgressIndex(UInt32 coderIndex);
|
||||
// Code
|
||||
// }
|
||||
|
||||
struct CSTCoderInfo: public CCoderInfo
|
||||
{
|
||||
bool IsMain;
|
||||
CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
|
||||
CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {}
|
||||
};
|
||||
|
||||
class CCoderMixer2ST:
|
||||
public ICompressCoder2,
|
||||
public CCoderMixer2,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
HRESULT GetInStream(
|
||||
ISequentialInStream **inStreams, const UInt64 **inSizes,
|
||||
UInt32 streamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetOutStream(
|
||||
ISequentialOutStream **outStreams, const UInt64 **outSizes,
|
||||
UInt32 streamIndex, ISequentialOutStream **outStreamRes);
|
||||
public:
|
||||
STDMETHOD(Code)(ISequentialInStream **inStreams,
|
||||
const UInt64 **inSizes,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 **outSizes,
|
||||
UInt32 numOutStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
CCoderMixer2ST();
|
||||
~CCoderMixer2ST();
|
||||
void AddCoderCommon(bool isMain);
|
||||
void AddCoder(ICompressCoder *coder, bool isMain);
|
||||
void AddCoder2(ICompressCoder2 *coder, bool isMain);
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
{
|
||||
{ _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
|
||||
}
|
||||
|
||||
void SetProgressCoderIndex(UInt32 /*coderIndex*/)
|
||||
{
|
||||
// _progressCoderIndex = coderIndex;
|
||||
}
|
||||
|
||||
// UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
|
||||
|
||||
private:
|
||||
CBindInfo _bindInfo;
|
||||
CObjectVector<CSTCoderInfo> _coders;
|
||||
int _mainCoderIndex;
|
||||
public:
|
||||
void SetBindInfo(const CBindInfo &bindInfo);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
15
CPP/7zip/Archive/Common/CrossThreadProgress.cpp
Executable file
15
CPP/7zip/Archive/Common/CrossThreadProgress.cpp
Executable file
@@ -0,0 +1,15 @@
|
||||
// CrossThreadProgress.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CrossThreadProgress.h"
|
||||
|
||||
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
InSize = inSize;
|
||||
OutSize = outSize;
|
||||
ProgressEvent.Set();
|
||||
WaitEvent.Lock();
|
||||
return Result;
|
||||
}
|
||||
|
||||
31
CPP/7zip/Archive/Common/CrossThreadProgress.h
Executable file
31
CPP/7zip/Archive/Common/CrossThreadProgress.h
Executable file
@@ -0,0 +1,31 @@
|
||||
// CrossThreadProgress.h
|
||||
|
||||
#ifndef __CROSSTHREADPROGRESS_H
|
||||
#define __CROSSTHREADPROGRESS_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
class CCrossThreadProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
const UInt64 *InSize;
|
||||
const UInt64 *OutSize;
|
||||
HRESULT Result;
|
||||
NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent WaitEvent;
|
||||
void Init()
|
||||
{
|
||||
ProgressEvent.Reset();
|
||||
WaitEvent.Reset();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
20
CPP/7zip/Archive/Common/DummyOutStream.cpp
Executable file
20
CPP/7zip/Archive/Common/DummyOutStream.cpp
Executable file
@@ -0,0 +1,20 @@
|
||||
// DummyOutStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "DummyOutStream.h"
|
||||
|
||||
void CDummyOutStream::Init(ISequentialOutStream *outStream)
|
||||
{
|
||||
m_Stream = outStream;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDummyOutStream::Write(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(m_Stream)
|
||||
return m_Stream->Write(data, size, processedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
23
CPP/7zip/Archive/Common/DummyOutStream.h
Executable file
23
CPP/7zip/Archive/Common/DummyOutStream.h
Executable file
@@ -0,0 +1,23 @@
|
||||
// DummyOutStream.h
|
||||
|
||||
#ifndef __DUMMYOUTSTREAM_H
|
||||
#define __DUMMYOUTSTREAM_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
class CDummyOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialOutStream> m_Stream;
|
||||
public:
|
||||
void Init(ISequentialOutStream *outStream);
|
||||
};
|
||||
|
||||
#endif
|
||||
243
CPP/7zip/Archive/Common/FilterCoder.cpp
Executable file
243
CPP/7zip/Archive/Common/FilterCoder.cpp
Executable file
@@ -0,0 +1,243 @@
|
||||
// FilterCoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "FilterCoder.h"
|
||||
#include "../../../Common/Alloc.h"
|
||||
#include "../../../Common/Defs.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
static const int kBufferSize = 1 << 17;
|
||||
|
||||
CFilterCoder::CFilterCoder()
|
||||
{
|
||||
_buffer = (Byte *)::MidAlloc(kBufferSize);
|
||||
}
|
||||
|
||||
CFilterCoder::~CFilterCoder()
|
||||
{
|
||||
::MidFree(_buffer);
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
|
||||
{
|
||||
if (_outSizeIsDefined)
|
||||
{
|
||||
UInt64 remSize = _outSize - _nowPos64;
|
||||
if (size > remSize)
|
||||
size = (UInt32)remSize;
|
||||
}
|
||||
UInt32 processedSize = 0;
|
||||
RINOK(WriteStream(outStream, _buffer, size, &processedSize));
|
||||
if (size != processedSize)
|
||||
return E_FAIL;
|
||||
_nowPos64 += processedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(Init());
|
||||
UInt32 bufferPos = 0;
|
||||
_outSizeIsDefined = (outSize != 0);
|
||||
if (_outSizeIsDefined)
|
||||
_outSize = *outSize;
|
||||
|
||||
while(NeedMore())
|
||||
{
|
||||
UInt32 processedSize;
|
||||
|
||||
// Change it: It can be optimized using ReadPart
|
||||
RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
|
||||
|
||||
UInt32 endPos = bufferPos + processedSize;
|
||||
|
||||
bufferPos = Filter->Filter(_buffer, endPos);
|
||||
if (bufferPos > endPos)
|
||||
{
|
||||
for (; endPos< bufferPos; endPos++)
|
||||
_buffer[endPos] = 0;
|
||||
bufferPos = Filter->Filter(_buffer, endPos);
|
||||
}
|
||||
|
||||
if (bufferPos == 0)
|
||||
{
|
||||
if (endPos > 0)
|
||||
return WriteWithLimit(outStream, endPos);
|
||||
return S_OK;
|
||||
}
|
||||
RINOK(WriteWithLimit(outStream, bufferPos));
|
||||
if (progress != NULL)
|
||||
{
|
||||
RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
|
||||
}
|
||||
UInt32 i = 0;
|
||||
while(bufferPos < endPos)
|
||||
_buffer[i++] = _buffer[bufferPos++];
|
||||
bufferPos = i;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// #ifdef _ST_MODE
|
||||
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
|
||||
{
|
||||
_bufferPos = 0;
|
||||
_outStream = outStream;
|
||||
return Init();
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseOutStream()
|
||||
{
|
||||
_outStream.Release();
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 processedSizeTotal = 0;
|
||||
while(size > 0)
|
||||
{
|
||||
UInt32 sizeMax = kBufferSize - _bufferPos;
|
||||
UInt32 sizeTemp = size;
|
||||
if (sizeTemp > sizeMax)
|
||||
sizeTemp = sizeMax;
|
||||
memmove(_buffer + _bufferPos, data, sizeTemp);
|
||||
size -= sizeTemp;
|
||||
processedSizeTotal += sizeTemp;
|
||||
data = (const Byte *)data + sizeTemp;
|
||||
UInt32 endPos = _bufferPos + sizeTemp;
|
||||
_bufferPos = Filter->Filter(_buffer, endPos);
|
||||
if (_bufferPos == 0)
|
||||
{
|
||||
_bufferPos = endPos;
|
||||
break;
|
||||
}
|
||||
if (_bufferPos > endPos)
|
||||
{
|
||||
if (size != 0)
|
||||
return E_FAIL;
|
||||
break;
|
||||
}
|
||||
RINOK(WriteWithLimit(_outStream, _bufferPos));
|
||||
UInt32 i = 0;
|
||||
while(_bufferPos < endPos)
|
||||
_buffer[i++] = _buffer[_bufferPos++];
|
||||
_bufferPos = i;
|
||||
}
|
||||
if (processedSize != NULL)
|
||||
*processedSize = processedSizeTotal;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Flush()
|
||||
{
|
||||
if (_bufferPos != 0)
|
||||
{
|
||||
UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
|
||||
if (endPos > _bufferPos)
|
||||
{
|
||||
for (; _bufferPos < endPos; _bufferPos++)
|
||||
_buffer[_bufferPos] = 0;
|
||||
if (Filter->Filter(_buffer, endPos) != endPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
UInt32 processedSize;
|
||||
RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
|
||||
if (_bufferPos != processedSize)
|
||||
return E_FAIL;
|
||||
_bufferPos = 0;
|
||||
}
|
||||
CMyComPtr<IOutStreamFlush> flush;
|
||||
_outStream.QueryInterface(IID_IOutStreamFlush, &flush);
|
||||
if (flush)
|
||||
return flush->Flush();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
|
||||
{
|
||||
_convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
|
||||
_inStream = inStream;
|
||||
return Init();
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseInStream()
|
||||
{
|
||||
_inStream.Release();
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 processedSizeTotal = 0;
|
||||
while(size > 0)
|
||||
{
|
||||
if (_convertedPosBegin != _convertedPosEnd)
|
||||
{
|
||||
UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
|
||||
memmove(data, _buffer + _convertedPosBegin, sizeTemp);
|
||||
_convertedPosBegin += sizeTemp;
|
||||
data = (void *)((Byte *)data + sizeTemp);
|
||||
size -= sizeTemp;
|
||||
processedSizeTotal += sizeTemp;
|
||||
break;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
|
||||
_buffer[i] = _buffer[i + _convertedPosEnd];
|
||||
_bufferPos = i;
|
||||
_convertedPosBegin = _convertedPosEnd = 0;
|
||||
UInt32 processedSizeTemp;
|
||||
UInt32 size0 = kBufferSize - _bufferPos;
|
||||
// Optimize it:
|
||||
RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
|
||||
_bufferPos = _bufferPos + processedSizeTemp;
|
||||
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
||||
if (_convertedPosEnd == 0)
|
||||
{
|
||||
if (_bufferPos == 0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
_convertedPosEnd = _bufferPos; // check it
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (_convertedPosEnd > _bufferPos)
|
||||
{
|
||||
for (; _bufferPos < _convertedPosEnd; _bufferPos++)
|
||||
_buffer[_bufferPos] = 0;
|
||||
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
||||
}
|
||||
}
|
||||
if (processedSize != NULL)
|
||||
*processedSize = processedSizeTotal;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// #endif // _ST_MODE
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
return _setPassword->CryptoSetPassword(data, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
return _writeCoderProperties->WriteCoderProperties(outStream);
|
||||
}
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
return _setDecoderProperties->SetDecoderProperties2(data, size);
|
||||
}
|
||||
130
CPP/7zip/Archive/Common/FilterCoder.h
Executable file
130
CPP/7zip/Archive/Common/FilterCoder.h
Executable file
@@ -0,0 +1,130 @@
|
||||
// FilterCoder.h
|
||||
|
||||
#ifndef __FILTERCODER_H
|
||||
#define __FILTERCODER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \
|
||||
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
|
||||
*outObject = (void *)(i *)this; AddRef(); return S_OK; }
|
||||
|
||||
class CFilterCoder:
|
||||
public ICompressCoder,
|
||||
// #ifdef _ST_MODE
|
||||
public ICompressSetInStream,
|
||||
public ISequentialInStream,
|
||||
public ICompressSetOutStream,
|
||||
public ISequentialOutStream,
|
||||
public IOutStreamFlush,
|
||||
// #endif
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoSetPassword,
|
||||
#endif
|
||||
#ifndef EXTRACT_ONLY
|
||||
public ICompressWriteCoderProperties,
|
||||
#endif
|
||||
public ICompressSetDecoderProperties2,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
protected:
|
||||
Byte *_buffer;
|
||||
// #ifdef _ST_MODE
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
CMyComPtr<ISequentialOutStream> _outStream;
|
||||
UInt32 _bufferPos;
|
||||
UInt32 _convertedPosBegin;
|
||||
UInt32 _convertedPosEnd;
|
||||
// #endif
|
||||
bool _outSizeIsDefined;
|
||||
UInt64 _outSize;
|
||||
UInt64 _nowPos64;
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
_nowPos64 = 0;
|
||||
_outSizeIsDefined = false;
|
||||
return Filter->Init();
|
||||
}
|
||||
|
||||
CMyComPtr<ICryptoSetPassword> _setPassword;
|
||||
#ifndef EXTRACT_ONLY
|
||||
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
|
||||
#endif
|
||||
CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;
|
||||
public:
|
||||
CMyComPtr<ICompressFilter> Filter;
|
||||
|
||||
CFilterCoder();
|
||||
~CFilterCoder();
|
||||
HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);
|
||||
bool NeedMore() const
|
||||
{ return (!_outSizeIsDefined || (_nowPos64 < _outSize)); }
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressCoder)
|
||||
// #ifdef _ST_MODE
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)
|
||||
// #endif
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
// #ifdef _ST_MODE
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
|
||||
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(ReleaseOutStream)();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Flush)();
|
||||
// #endif
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
#endif
|
||||
#ifndef EXTRACT_ONLY
|
||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
#endif
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
};
|
||||
|
||||
// #ifdef _ST_MODE
|
||||
class CInStreamReleaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
CInStreamReleaser(): FilterCoder(0) {}
|
||||
~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
|
||||
};
|
||||
|
||||
class COutStreamReleaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
COutStreamReleaser(): FilterCoder(0) {}
|
||||
~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
|
||||
};
|
||||
// #endif
|
||||
|
||||
#endif
|
||||
41
CPP/7zip/Archive/Common/InStreamWithCRC.cpp
Executable file
41
CPP/7zip/Archive/Common/InStreamWithCRC.cpp
Executable file
@@ -0,0 +1,41 @@
|
||||
// InStreamWithCRC.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "InStreamWithCRC.h"
|
||||
|
||||
STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (size > 0 && realProcessedSize == 0)
|
||||
_wasFinished = true;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
if (size > 0 && realProcessedSize == 0)
|
||||
_wasFinished = true;
|
||||
_size += realProcessedSize;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset,
|
||||
UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (seekOrigin != STREAM_SEEK_SET || offset != 0)
|
||||
return E_FAIL;
|
||||
_size = 0;
|
||||
_crc.Init();
|
||||
return _stream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
65
CPP/7zip/Archive/Common/InStreamWithCRC.h
Executable file
65
CPP/7zip/Archive/Common/InStreamWithCRC.h
Executable file
@@ -0,0 +1,65 @@
|
||||
// InStreamWithCRC.h
|
||||
|
||||
#ifndef __INSTREAMWITHCRC_H
|
||||
#define __INSTREAMWITHCRC_H
|
||||
|
||||
#include "../../../Common/CRC.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
class CSequentialInStreamWithCRC:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
_wasFinished = false;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
class CInStreamWithCRC:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
private:
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
_wasFinished = false;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
#endif
|
||||
59
CPP/7zip/Archive/Common/ItemNameUtils.cpp
Executable file
59
CPP/7zip/Archive/Common/ItemNameUtils.cpp
Executable file
@@ -0,0 +1,59 @@
|
||||
// Archive/Common/ItemNameUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ItemNameUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
|
||||
static const wchar_t kDirDelimiter = L'/';
|
||||
|
||||
UString MakeLegalName(const UString &name)
|
||||
{
|
||||
UString zipName = name;
|
||||
zipName.Replace(kOSDirDelimiter, kDirDelimiter);
|
||||
return zipName;
|
||||
}
|
||||
|
||||
UString GetOSName(const UString &name)
|
||||
{
|
||||
UString newName = name;
|
||||
newName.Replace(kDirDelimiter, kOSDirDelimiter);
|
||||
return newName;
|
||||
}
|
||||
|
||||
UString GetOSName2(const UString &name)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return UString();
|
||||
UString newName = GetOSName(name);
|
||||
if (newName[newName.Length() - 1] == kOSDirDelimiter)
|
||||
newName.Delete(newName.Length() - 1);
|
||||
return newName;
|
||||
}
|
||||
|
||||
bool HasTailSlash(const AString &name, UINT codePage)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
LPCSTR prev =
|
||||
#ifdef _WIN32
|
||||
CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
|
||||
#else
|
||||
(LPCSTR)(name) + (name.Length() - 1);
|
||||
#endif
|
||||
return (*prev == '/');
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
UString WinNameToOSName(const UString &name)
|
||||
{
|
||||
UString newName = name;
|
||||
newName.Replace(L'\\', kOSDirDelimiter);
|
||||
return newName;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}
|
||||
24
CPP/7zip/Archive/Common/ItemNameUtils.h
Executable file
24
CPP/7zip/Archive/Common/ItemNameUtils.h
Executable file
@@ -0,0 +1,24 @@
|
||||
// Archive/Common/ItemNameUtils.h
|
||||
|
||||
#ifndef __ARCHIVE_ITEMNAMEUTILS_H
|
||||
#define __ARCHIVE_ITEMNAMEUTILS_H
|
||||
|
||||
#include "../../../Common/String.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
UString MakeLegalName(const UString &name);
|
||||
UString GetOSName(const UString &name);
|
||||
UString GetOSName2(const UString &name);
|
||||
bool HasTailSlash(const AString &name, UINT codePage);
|
||||
|
||||
#ifdef _WIN32
|
||||
inline UString WinNameToOSName(const UString &name) { return name; }
|
||||
#else
|
||||
UString WinNameToOSName(const UString &name);
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
201
CPP/7zip/Archive/Common/MultiStream.cpp
Executable file
201
CPP/7zip/Archive/Common/MultiStream.cpp
Executable file
@@ -0,0 +1,201 @@
|
||||
// MultiStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "MultiStream.h"
|
||||
|
||||
STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(processedSize != NULL)
|
||||
*processedSize = 0;
|
||||
while(_streamIndex < Streams.Size() && size > 0)
|
||||
{
|
||||
CSubStreamInfo &s = Streams[_streamIndex];
|
||||
if (_pos == s.Size)
|
||||
{
|
||||
_streamIndex++;
|
||||
_pos = 0;
|
||||
continue;
|
||||
}
|
||||
RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0));
|
||||
UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
|
||||
UInt32 realProcessed;
|
||||
HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
|
||||
data = (void *)((Byte *)data + realProcessed);
|
||||
size -= realProcessed;
|
||||
if(processedSize != NULL)
|
||||
*processedSize += realProcessed;
|
||||
_pos += realProcessed;
|
||||
_seekPos += realProcessed;
|
||||
RINOK(result);
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
UInt64 *newPosition)
|
||||
{
|
||||
UInt64 newPos;
|
||||
switch(seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
newPos = offset;
|
||||
break;
|
||||
case STREAM_SEEK_CUR:
|
||||
newPos = _seekPos + offset;
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
newPos = _totalLength + offset;
|
||||
break;
|
||||
default:
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
_seekPos = 0;
|
||||
for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
|
||||
{
|
||||
UInt64 size = Streams[_streamIndex].Size;
|
||||
if (newPos < _seekPos + size)
|
||||
{
|
||||
_pos = newPos - _seekPos;
|
||||
_seekPos += _pos;
|
||||
if (newPosition != 0)
|
||||
*newPosition = newPos;
|
||||
return S_OK;
|
||||
}
|
||||
_seekPos += size;
|
||||
}
|
||||
if (newPos == _seekPos)
|
||||
{
|
||||
if (newPosition != 0)
|
||||
*newPosition = newPos;
|
||||
return S_OK;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class COutVolumeStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
int _volIndex;
|
||||
UInt64 _volSize;
|
||||
UInt64 _curPos;
|
||||
CMyComPtr<ISequentialOutStream> _volumeStream;
|
||||
COutArchive _archive;
|
||||
CCRC _crc;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
CFileItem _file;
|
||||
CUpdateOptions _options;
|
||||
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
|
||||
void Init(IArchiveUpdateCallback2 *volumeCallback,
|
||||
const UString &name)
|
||||
{
|
||||
_file.Name = name;
|
||||
_file.IsStartPosDefined = true;
|
||||
_file.StartPos = 0;
|
||||
|
||||
VolumeCallback = volumeCallback;
|
||||
_volIndex = 0;
|
||||
_volSize = 0;
|
||||
}
|
||||
|
||||
HRESULT Flush();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
HRESULT COutVolumeStream::Flush()
|
||||
{
|
||||
if (_volumeStream)
|
||||
{
|
||||
_file.UnPackSize = _curPos;
|
||||
_file.FileCRC = _crc.GetDigest();
|
||||
RINOK(WriteVolumeHeader(_archive, _file, _options));
|
||||
_archive.Close();
|
||||
_volumeStream.Release();
|
||||
_file.StartPos += _file.UnPackSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(processedSize != NULL)
|
||||
*processedSize = 0;
|
||||
while(size > 0)
|
||||
{
|
||||
if (_streamIndex >= Streams.Size())
|
||||
{
|
||||
CSubStreamInfo subStream;
|
||||
RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
|
||||
RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
|
||||
subStream.Pos = 0;
|
||||
Streams.Add(subStream);
|
||||
continue;
|
||||
}
|
||||
CSubStreamInfo &subStream = Streams[_streamIndex];
|
||||
if (_offsetPos >= subStream.Size)
|
||||
{
|
||||
_offsetPos -= subStream.Size;
|
||||
_streamIndex++;
|
||||
continue;
|
||||
}
|
||||
if (_offsetPos != subStream.Pos)
|
||||
{
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
|
||||
RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
|
||||
subStream.Pos = _offsetPos;
|
||||
}
|
||||
|
||||
UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
|
||||
UInt32 realProcessed;
|
||||
RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
|
||||
data = (void *)((Byte *)data + realProcessed);
|
||||
size -= realProcessed;
|
||||
subStream.Pos += realProcessed;
|
||||
_offsetPos += realProcessed;
|
||||
_absPos += realProcessed;
|
||||
if (_absPos > _length)
|
||||
_length = _absPos;
|
||||
if(processedSize != NULL)
|
||||
*processedSize += realProcessed;
|
||||
if (subStream.Pos == subStream.Size)
|
||||
{
|
||||
_streamIndex++;
|
||||
_offsetPos = 0;
|
||||
}
|
||||
if (realProcessed != curSize && realProcessed == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if(seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
switch(seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
_absPos = offset;
|
||||
break;
|
||||
case STREAM_SEEK_CUR:
|
||||
_absPos += offset;
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
_absPos = _length + offset;
|
||||
break;
|
||||
}
|
||||
_offsetPos = _absPos;
|
||||
_streamIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
76
CPP/7zip/Archive/Common/MultiStream.h
Executable file
76
CPP/7zip/Archive/Common/MultiStream.h
Executable file
@@ -0,0 +1,76 @@
|
||||
// MultiStream.h
|
||||
|
||||
#ifndef __MULTISTREAM_H
|
||||
#define __MULTISTREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/Vector.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
class CMultiStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
int _streamIndex;
|
||||
UInt64 _pos;
|
||||
UInt64 _seekPos;
|
||||
UInt64 _totalLength;
|
||||
public:
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Pos;
|
||||
UInt64 Size;
|
||||
};
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
void Init()
|
||||
{
|
||||
_streamIndex = 0;
|
||||
_pos = 0;
|
||||
_seekPos = 0;
|
||||
_totalLength = 0;
|
||||
for (int i = 0; i < Streams.Size(); i++)
|
||||
_totalLength += Streams[i].Size;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
/*
|
||||
class COutMultiStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
int _streamIndex; // required stream
|
||||
UInt64 _offsetPos; // offset from start of _streamIndex index
|
||||
UInt64 _absPos;
|
||||
UInt64 _length;
|
||||
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> Stream;
|
||||
UInt64 Size;
|
||||
UInt64 Pos;
|
||||
};
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
public:
|
||||
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
|
||||
void Init()
|
||||
{
|
||||
_streamIndex = 0;
|
||||
_offsetPos = 0;
|
||||
_absPos = 0;
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(IOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
24
CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
Executable file
24
CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
Executable file
@@ -0,0 +1,24 @@
|
||||
// OutStreamWithCRC.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutStreamWithCRC.h"
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
result = S_OK;
|
||||
}
|
||||
else
|
||||
result = _stream->Write(data, size, &realProcessedSize);
|
||||
if (_calculateCrc)
|
||||
_crc.Update(data, realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
37
CPP/7zip/Archive/Common/OutStreamWithCRC.h
Executable file
37
CPP/7zip/Archive/Common/OutStreamWithCRC.h
Executable file
@@ -0,0 +1,37 @@
|
||||
// OutStreamWithCRC.h
|
||||
|
||||
#ifndef __OUTSTREAMWITHCRC_H
|
||||
#define __OUTSTREAMWITHCRC_H
|
||||
|
||||
#include "../../../Common/CRC.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
class COutStreamWithCRC:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
bool _calculateCrc;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init(bool calculateCrc = true)
|
||||
{
|
||||
_size = 0;
|
||||
_calculateCrc = calculateCrc;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
void InitCRC() { _crc.Init(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
171
CPP/7zip/Archive/Common/ParseProperties.cpp
Executable file
171
CPP/7zip/Archive/Common/ParseProperties.cpp
Executable file
@@ -0,0 +1,171 @@
|
||||
// ParseProperties.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ParseProperties.h"
|
||||
|
||||
#include "Common/StringToInt.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
|
||||
{
|
||||
if (prop.vt == VT_UI4)
|
||||
{
|
||||
if (!name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
resValue = prop.ulVal;
|
||||
}
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
{
|
||||
if(!name.IsEmpty())
|
||||
{
|
||||
const wchar_t *start = name;
|
||||
const wchar_t *end;
|
||||
UInt64 v = ConvertStringToUInt64(start, &end);
|
||||
if (end - start != name.Length())
|
||||
return E_INVALIDARG;
|
||||
resValue = (UInt32)v;
|
||||
}
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const int kLogarithmicSizeLimit = 32;
|
||||
static const wchar_t kByteSymbol = L'B';
|
||||
static const wchar_t kKiloByteSymbol = L'K';
|
||||
static const wchar_t kMegaByteSymbol = L'M';
|
||||
|
||||
HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
|
||||
{
|
||||
UString srcString = srcStringSpec;
|
||||
srcString.MakeUpper();
|
||||
|
||||
const wchar_t *start = srcString;
|
||||
const wchar_t *end;
|
||||
UInt64 number = ConvertStringToUInt64(start, &end);
|
||||
int numDigits = (int)(end - start);
|
||||
if (numDigits == 0 || srcString.Length() > numDigits + 1)
|
||||
return E_INVALIDARG;
|
||||
if (srcString.Length() == numDigits)
|
||||
{
|
||||
if (number >= kLogarithmicSizeLimit)
|
||||
return E_INVALIDARG;
|
||||
dicSize = (UInt32)1 << (int)number;
|
||||
return S_OK;
|
||||
}
|
||||
switch (srcString[numDigits])
|
||||
{
|
||||
case kByteSymbol:
|
||||
if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
|
||||
return E_INVALIDARG;
|
||||
dicSize = (UInt32)number;
|
||||
break;
|
||||
case kKiloByteSymbol:
|
||||
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
|
||||
return E_INVALIDARG;
|
||||
dicSize = (UInt32)(number << 10);
|
||||
break;
|
||||
case kMegaByteSymbol:
|
||||
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
|
||||
return E_INVALIDARG;
|
||||
dicSize = (UInt32)(number << 20);
|
||||
break;
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
{
|
||||
if (prop.vt == VT_UI4)
|
||||
{
|
||||
UInt32 logDicSize = prop.ulVal;
|
||||
if (logDicSize >= 32)
|
||||
return E_INVALIDARG;
|
||||
resValue = (UInt32)1 << logDicSize;
|
||||
return S_OK;
|
||||
}
|
||||
if (prop.vt == VT_BSTR)
|
||||
return ParsePropDictionaryValue(prop.bstrVal, resValue);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
return ParsePropDictionaryValue(name, resValue);
|
||||
}
|
||||
|
||||
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
|
||||
{
|
||||
switch(value.vt)
|
||||
{
|
||||
case VT_EMPTY:
|
||||
dest = true;
|
||||
break;
|
||||
/*
|
||||
case VT_UI4:
|
||||
dest = (value.ulVal != 0);
|
||||
break;
|
||||
*/
|
||||
case VT_BSTR:
|
||||
{
|
||||
UString valueString = value.bstrVal;
|
||||
valueString.MakeUpper();
|
||||
if (valueString.Compare(L"ON") == 0)
|
||||
dest = true;
|
||||
else if (valueString.Compare(L"OFF") == 0)
|
||||
dest = false;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int ParseStringToUInt32(const UString &srcString, UInt32 &number)
|
||||
{
|
||||
const wchar_t *start = srcString;
|
||||
const wchar_t *end;
|
||||
UInt64 number64 = ConvertStringToUInt64(start, &end);
|
||||
if (number64 > 0xFFFFFFFF)
|
||||
{
|
||||
number = 0;
|
||||
return 0;
|
||||
}
|
||||
number = (UInt32)number64;
|
||||
return (int)(end - start);
|
||||
}
|
||||
|
||||
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
{
|
||||
switch(prop.vt)
|
||||
{
|
||||
case VT_UI4:
|
||||
numThreads = prop.ulVal;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
bool val;
|
||||
RINOK(SetBoolProperty(val, prop));
|
||||
numThreads = (val ? defaultNumThreads : 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
if (index != name.Length())
|
||||
return E_INVALIDARG;
|
||||
numThreads = number;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
17
CPP/7zip/Archive/Common/ParseProperties.h
Executable file
17
CPP/7zip/Archive/Common/ParseProperties.h
Executable file
@@ -0,0 +1,17 @@
|
||||
// ParseProperties.h
|
||||
|
||||
#ifndef __PARSEPROPERTIES_H
|
||||
#define __PARSEPROPERTIES_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/Types.h"
|
||||
|
||||
HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
|
||||
HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
|
||||
HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
|
||||
|
||||
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
|
||||
int ParseStringToUInt32(const UString &srcString, UInt32 &number);
|
||||
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
|
||||
|
||||
#endif
|
||||
9
CPP/7zip/Archive/Common/StdAfx.h
Executable file
9
CPP/7zip/Archive/Common/StdAfx.h
Executable file
@@ -0,0 +1,9 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/NewHandler.h"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user