mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 22:07:08 -06:00
23.01
This commit is contained in:
@@ -57,9 +57,9 @@ HRESULT SResToHRESULT(SRes res) throw()
|
||||
#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)
|
||||
|
||||
|
||||
static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw()
|
||||
static SRes CompressProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) throw()
|
||||
{
|
||||
CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt);
|
||||
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CCompressProgressWrap)
|
||||
p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));
|
||||
return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
|
||||
}
|
||||
@@ -73,9 +73,9 @@ void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()
|
||||
|
||||
static const UInt32 kStreamStepSize = (UInt32)1 << 31;
|
||||
|
||||
static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
|
||||
static SRes MyRead(ISeqInStreamPtr pp, void *data, size_t *size) throw()
|
||||
{
|
||||
CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt);
|
||||
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqInStreamWrap)
|
||||
UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
|
||||
p->Res = (p->Stream->Read(data, curSize, &curSize));
|
||||
*size = curSize;
|
||||
@@ -85,9 +85,9 @@ static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
|
||||
return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);
|
||||
}
|
||||
|
||||
static size_t MyWrite(const ISeqOutStream *pp, const void *data, size_t size) throw()
|
||||
static size_t MyWrite(ISeqOutStreamPtr pp, const void *data, size_t size) throw()
|
||||
{
|
||||
CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt);
|
||||
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqOutStreamWrap)
|
||||
if (p->Stream)
|
||||
{
|
||||
p->Res = WriteStream(p->Stream, data, size);
|
||||
@@ -118,20 +118,23 @@ void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()
|
||||
}
|
||||
|
||||
|
||||
static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw()
|
||||
static SRes InStreamWrap_Read(ISeekInStreamPtr pp, void *data, size_t *size) throw()
|
||||
{
|
||||
CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
|
||||
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeekInStreamWrap)
|
||||
UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
|
||||
p->Res = p->Stream->Read(data, curSize, &curSize);
|
||||
*size = curSize;
|
||||
return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
static SRes InStreamWrap_Seek(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw()
|
||||
static SRes InStreamWrap_Seek(ISeekInStreamPtr pp, Int64 *offset, ESzSeek origin) throw()
|
||||
{
|
||||
CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
|
||||
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeekInStreamWrap)
|
||||
UInt32 moveMethod;
|
||||
switch (origin)
|
||||
/* we need (int)origin to eliminate the clang warning:
|
||||
default label in switch which covers all enumeration values
|
||||
[-Wcovered-switch-default */
|
||||
switch ((int)origin)
|
||||
{
|
||||
case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;
|
||||
case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;
|
||||
@@ -188,15 +191,18 @@ Byte CByteInBufWrap::ReadByteFromNewBlock() throw()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Byte Wrap_ReadByte(const IByteIn *pp) throw()
|
||||
// #pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||
|
||||
static Byte Wrap_ReadByte(IByteInPtr pp) throw()
|
||||
{
|
||||
CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
|
||||
CByteInBufWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
|
||||
// Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteInBufWrap)
|
||||
if (p->Cur != p->Lim)
|
||||
return *p->Cur++;
|
||||
return p->ReadByteFromNewBlock();
|
||||
}
|
||||
|
||||
CByteInBufWrap::CByteInBufWrap(): Buf(NULL)
|
||||
CByteInBufWrap::CByteInBufWrap() throw(): Buf(NULL)
|
||||
{
|
||||
vt.Read = Wrap_ReadByte;
|
||||
}
|
||||
@@ -227,7 +233,7 @@ bool CLookToSequentialWrap::Alloc(UInt32 size) throw()
|
||||
/*
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
void CLookToSequentialWrap_Look(ILookInSeqStream *pp)
|
||||
void CLookToSequentialWrap_Look(ILookInSeqStreamPtr pp)
|
||||
{
|
||||
CLookToSequentialWrap *p = (CLookToSequentialWrap *)pp->Obj;
|
||||
|
||||
@@ -281,9 +287,10 @@ HRESULT CByteOutBufWrap::Flush() throw()
|
||||
return Res;
|
||||
}
|
||||
|
||||
static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw()
|
||||
static void Wrap_WriteByte(IByteOutPtr pp, Byte b) throw()
|
||||
{
|
||||
CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
|
||||
CByteOutBufWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
|
||||
// Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteOutBufWrap)
|
||||
Byte *dest = p->Cur;
|
||||
*dest = b;
|
||||
p->Cur = ++dest;
|
||||
@@ -317,16 +324,16 @@ bool CLookOutWrap::Alloc(size_t size) throw()
|
||||
return (Buf != NULL);
|
||||
}
|
||||
|
||||
static size_t LookOutWrap_GetOutBuf(const ILookOutStream *pp, void **buf) throw()
|
||||
static size_t LookOutWrap_GetOutBuf(ILookOutStreamPtr pp, void **buf) throw()
|
||||
{
|
||||
CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt);
|
||||
CLookOutWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt);
|
||||
*buf = p->Buf;
|
||||
return p->Size;
|
||||
}
|
||||
|
||||
static size_t LookOutWrap_Write(const ILookOutStream *pp, size_t size) throw()
|
||||
static size_t LookOutWrap_Write(ILookOutStreamPtr pp, size_t size) throw()
|
||||
{
|
||||
CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt);
|
||||
CLookOutWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt);
|
||||
if (p->Res == S_OK && size != 0)
|
||||
{
|
||||
p->Res = WriteStream(p->Stream, p->Buf, size);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// CWrappers.h
|
||||
|
||||
#ifndef __C_WRAPPERS_H
|
||||
#define __C_WRAPPERS_H
|
||||
#ifndef ZIP7_INC_C_WRAPPERS_H
|
||||
#define ZIP7_INC_C_WRAPPERS_H
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
@@ -63,7 +63,7 @@ struct CByteInBufWrap
|
||||
bool Extra;
|
||||
HRESULT Res;
|
||||
|
||||
CByteInBufWrap();
|
||||
CByteInBufWrap() throw();
|
||||
~CByteInBufWrap() { Free(); }
|
||||
void Free() throw();
|
||||
bool Alloc(UInt32 size) throw();
|
||||
|
||||
@@ -19,11 +19,11 @@ const CCodecInfo *g_Codecs[];
|
||||
const CCodecInfo *g_Codecs[kNumCodecsMax];
|
||||
|
||||
// We use g_ExternalCodecs in other stages.
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
/*
|
||||
extern CExternalCodecs g_ExternalCodecs;
|
||||
#define CHECK_GLOBAL_CODECS \
|
||||
if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs;
|
||||
if (!_externalCodecs || !_externalCodecs->IsSet()) _externalCodecs = &g_ExternalCodecs;
|
||||
*/
|
||||
#define CHECK_GLOBAL_CODECS
|
||||
#endif
|
||||
@@ -50,12 +50,12 @@ void RegisterHasher(const CHasherInfo *hashInfo) throw()
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
RINOK(codecsInfo->GetProperty(index, propID, &prop));
|
||||
RINOK(codecsInfo->GetProperty(index, propID, &prop))
|
||||
if (prop.vt == VT_EMPTY)
|
||||
res = 1;
|
||||
else if (prop.vt == VT_UI4)
|
||||
@@ -68,7 +68,7 @@ static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index
|
||||
static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
RINOK(codecsInfo->GetProperty(index, propID, &prop));
|
||||
RINOK(codecsInfo->GetProperty(index, propID, &prop))
|
||||
if (prop.vt == VT_EMPTY)
|
||||
res = true;
|
||||
else if (prop.vt == VT_BOOL)
|
||||
@@ -89,13 +89,13 @@ HRESULT CExternalCodecs::Load()
|
||||
|
||||
UString s;
|
||||
UInt32 num;
|
||||
RINOK(GetCodecs->GetNumMethods(&num));
|
||||
RINOK(GetCodecs->GetNumMethods(&num))
|
||||
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
|
||||
RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop));
|
||||
RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop))
|
||||
if (prop.vt != VT_UI8)
|
||||
continue; // old Interface
|
||||
info.Id = prop.uhVal.QuadPart;
|
||||
@@ -103,22 +103,22 @@ HRESULT CExternalCodecs::Load()
|
||||
prop.Clear();
|
||||
|
||||
info.Name.Empty();
|
||||
RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop));
|
||||
RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop))
|
||||
if (prop.vt == VT_BSTR)
|
||||
info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
continue;
|
||||
|
||||
RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams));
|
||||
RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams))
|
||||
{
|
||||
UInt32 numUnpackStreams = 1;
|
||||
RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams));
|
||||
RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams))
|
||||
if (numUnpackStreams != 1)
|
||||
continue;
|
||||
}
|
||||
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
|
||||
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
|
||||
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter));
|
||||
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned))
|
||||
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned))
|
||||
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter))
|
||||
|
||||
Codecs.Add(info);
|
||||
}
|
||||
@@ -133,7 +133,7 @@ HRESULT CExternalCodecs::Load()
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
|
||||
RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop));
|
||||
RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop))
|
||||
if (prop.vt != VT_UI8)
|
||||
continue;
|
||||
info.Id = prop.uhVal.QuadPart;
|
||||
@@ -141,7 +141,7 @@ HRESULT CExternalCodecs::Load()
|
||||
prop.Clear();
|
||||
|
||||
info.Name.Empty();
|
||||
RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop));
|
||||
RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop))
|
||||
if (prop.vt == VT_BSTR)
|
||||
info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
@@ -162,7 +162,8 @@ int FindMethod_Index(
|
||||
const AString &name,
|
||||
bool encode,
|
||||
CMethodId &methodId,
|
||||
UInt32 &numStreams)
|
||||
UInt32 &numStreams,
|
||||
bool &isFilter)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < g_NumCodecs; i++)
|
||||
@@ -173,23 +174,25 @@ int FindMethod_Index(
|
||||
{
|
||||
methodId = codec.Id;
|
||||
numStreams = codec.NumStreams;
|
||||
isFilter = codec.IsFilter;
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
|
||||
if (_externalCodecs)
|
||||
for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
|
||||
if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
|
||||
&& StringsAreEqualNoCase_Ascii(name, codec.Name))
|
||||
{
|
||||
methodId = codec.Id;
|
||||
numStreams = codec.NumStreams;
|
||||
isFilter = codec.IsFilter;
|
||||
return (int)(g_NumCodecs + i);
|
||||
}
|
||||
}
|
||||
@@ -212,14 +215,14 @@ static int FindMethod_Index(
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
|
||||
if (_externalCodecs)
|
||||
for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
|
||||
if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
|
||||
return (int)(g_NumCodecs + i);
|
||||
}
|
||||
@@ -248,14 +251,14 @@ bool FindMethod(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
|
||||
if (_externalCodecs)
|
||||
for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
|
||||
if (methodId == codec.Id)
|
||||
{
|
||||
name = codec.Name;
|
||||
@@ -284,14 +287,14 @@ bool FindHashMethod(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
|
||||
if (_externalCodecs)
|
||||
for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
|
||||
{
|
||||
const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
|
||||
const CHasherInfoEx &codec = _externalCodecs->Hashers[i];
|
||||
if (StringsAreEqualNoCase_Ascii(name, codec.Name))
|
||||
{
|
||||
methodId = codec.Id;
|
||||
@@ -313,13 +316,13 @@ void GetHashMethods(
|
||||
for (i = 0; i < g_NumHashers; i++)
|
||||
methods[i] = (*g_Hashers[i]).Id;
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
|
||||
methods.Add(__externalCodecs->Hashers[i].Id);
|
||||
if (_externalCodecs)
|
||||
for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
|
||||
methods.Add(_externalCodecs->Hashers[i].Id);
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -364,17 +367,17 @@ HRESULT CreateCoder_Index(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
if (_externalCodecs)
|
||||
{
|
||||
i -= g_NumCodecs;
|
||||
cod.IsExternal = true;
|
||||
if (i < __externalCodecs->Codecs.Size())
|
||||
if (i < _externalCodecs->Codecs.Size())
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
|
||||
// if (codec.Id == methodId)
|
||||
{
|
||||
if (encode)
|
||||
@@ -383,15 +386,15 @@ HRESULT CreateCoder_Index(
|
||||
{
|
||||
if (codec.NumStreams == 1)
|
||||
{
|
||||
HRESULT res = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
|
||||
const HRESULT res = _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
|
||||
if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
|
||||
return res;
|
||||
if (cod.Coder)
|
||||
return res;
|
||||
return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);
|
||||
return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);
|
||||
}
|
||||
cod.NumStreams = codec.NumStreams;
|
||||
return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
|
||||
return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -399,15 +402,15 @@ HRESULT CreateCoder_Index(
|
||||
{
|
||||
if (codec.NumStreams == 1)
|
||||
{
|
||||
HRESULT res = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
|
||||
const HRESULT res = _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
|
||||
if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
|
||||
return res;
|
||||
if (cod.Coder)
|
||||
return res;
|
||||
return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);
|
||||
return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);
|
||||
}
|
||||
cod.NumStreams = codec.NumStreams;
|
||||
return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
|
||||
return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,7 +427,7 @@ HRESULT CreateCoder_Index(
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
CMyComPtr<ICompressFilter> filter;
|
||||
HRESULT res = CreateCoder_Index(
|
||||
const HRESULT res = CreateCoder_Index(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
index, encode,
|
||||
filter, cod);
|
||||
@@ -447,7 +450,7 @@ HRESULT CreateCoder_Id(
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
|
||||
const int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
|
||||
if (index < 0)
|
||||
return S_OK;
|
||||
return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod);
|
||||
@@ -460,7 +463,7 @@ HRESULT CreateCoder_Id(
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
CMyComPtr<ICompressFilter> filter;
|
||||
HRESULT res = CreateCoder_Id(
|
||||
const HRESULT res = CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, encode,
|
||||
filter, cod);
|
||||
@@ -483,7 +486,7 @@ HRESULT CreateCoder_Id(
|
||||
CMyComPtr<ICompressCoder> &coder)
|
||||
{
|
||||
CCreatedCoder cod;
|
||||
HRESULT res = CreateCoder_Id(
|
||||
const HRESULT res = CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, encode,
|
||||
cod);
|
||||
@@ -524,18 +527,18 @@ HRESULT CreateHasher(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (!hasher && __externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
|
||||
if (!hasher && _externalCodecs)
|
||||
for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
|
||||
{
|
||||
const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
|
||||
const CHasherInfoEx &codec = _externalCodecs->Hashers[i];
|
||||
if (codec.Id == methodId)
|
||||
{
|
||||
name = codec.Name;
|
||||
return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);
|
||||
return _externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// CreateCoder.h
|
||||
|
||||
#ifndef __CREATE_CODER_H
|
||||
#define __CREATE_CODER_H
|
||||
#ifndef ZIP7_INC_CREATE_CODER_H
|
||||
#define ZIP7_INC_CREATE_CODER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyString.h"
|
||||
@@ -11,10 +11,10 @@
|
||||
#include "MethodId.h"
|
||||
|
||||
/*
|
||||
if EXTERNAL_CODECS is not defined, the code supports only codecs that
|
||||
if Z7_EXTERNAL_CODECS is not defined, the code supports only codecs that
|
||||
are statically linked at compile-time and link-time.
|
||||
|
||||
if EXTERNAL_CODECS is defined, the code supports also codecs from another
|
||||
if Z7_EXTERNAL_CODECS is defined, the code supports also codecs from another
|
||||
executable modules, that can be linked dynamically at run-time:
|
||||
- EXE module can use codecs from external DLL files.
|
||||
- DLL module can use codecs from external EXE and DLL files.
|
||||
@@ -26,7 +26,7 @@
|
||||
2) External codecs
|
||||
*/
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
struct CCodecInfoEx
|
||||
{
|
||||
@@ -46,13 +46,17 @@ struct CHasherInfoEx
|
||||
AString Name;
|
||||
};
|
||||
|
||||
#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
|
||||
#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
|
||||
#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
|
||||
#define IMPL_ISetCompressCodecsInfo2(x) \
|
||||
STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
|
||||
COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END }
|
||||
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
|
||||
#define Z7_PUBLIC_ISetCompressCodecsInfo_IFEC \
|
||||
public ISetCompressCodecsInfo,
|
||||
#define Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC \
|
||||
Z7_COM_QI_ENTRY(ISetCompressCodecsInfo)
|
||||
#define DECL_ISetCompressCodecsInfo \
|
||||
Z7_COM7F_IMP(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo))
|
||||
#define IMPL_ISetCompressCodecsInfo2(cls) \
|
||||
Z7_COM7F_IMF(cls::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo)) \
|
||||
{ COM_TRY_BEGIN _externalCodecs.GetCodecs = compressCodecsInfo; \
|
||||
return _externalCodecs.Load(); COM_TRY_END }
|
||||
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
|
||||
|
||||
struct CExternalCodecs
|
||||
{
|
||||
@@ -83,26 +87,27 @@ struct CExternalCodecs
|
||||
|
||||
extern CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
#define EXTERNAL_CODECS_VARS2 (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2 (_externalCodecs.IsSet() ? &_externalCodecs : &g_ExternalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_L (&_externalCodecs)
|
||||
#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs)
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs;
|
||||
#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs _externalCodecs;
|
||||
|
||||
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
|
||||
#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L,
|
||||
#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G,
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs
|
||||
#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *_externalCodecs
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS_DECL DECL_EXTERNAL_CODECS_LOC_VARS2;
|
||||
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
|
||||
#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
|
||||
#define EXTERNAL_CODECS_LOC_VARS2 _externalCodecs
|
||||
#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
|
||||
|
||||
#else
|
||||
|
||||
#define PUBLIC_ISetCompressCodecsInfo
|
||||
#define QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
#define Z7_PUBLIC_ISetCompressCodecsInfo_IFEC
|
||||
#define Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC
|
||||
#define DECL_ISetCompressCodecsInfo
|
||||
#define IMPL_ISetCompressCodecsInfo
|
||||
#define EXTERNAL_CODECS_VARS2
|
||||
@@ -111,8 +116,9 @@ extern CExternalCodecs g_ExternalCodecs;
|
||||
#define EXTERNAL_CODECS_VARS_L
|
||||
#define EXTERNAL_CODECS_VARS_G
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS2
|
||||
#define EXTERNAL_CODECS_LOC_VARS2
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
#define DECL_EXTERNAL_CODECS_LOC_VARS_DECL
|
||||
#define EXTERNAL_CODECS_LOC_VARS2
|
||||
#define EXTERNAL_CODECS_LOC_VARS
|
||||
|
||||
#endif
|
||||
@@ -122,7 +128,8 @@ int FindMethod_Index(
|
||||
const AString &name,
|
||||
bool encode,
|
||||
CMethodId &methodId,
|
||||
UInt32 &numStreams);
|
||||
UInt32 &numStreams,
|
||||
bool &isFilter);
|
||||
|
||||
bool FindMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FilePathAutoRename.h
|
||||
|
||||
#ifndef __FILE_PATH_AUTO_RENAME_H
|
||||
#define __FILE_PATH_AUTO_RENAME_H
|
||||
#ifndef ZIP7_INC_FILE_PATH_AUTO_RENAME_H
|
||||
#define ZIP7_INC_FILE_PATH_AUTO_RENAME_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
|
||||
@@ -11,15 +11,20 @@
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
// for major minor
|
||||
// BSD: <sys/types.h>
|
||||
// for major()/minor():
|
||||
#include <sys/types.h>
|
||||
#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__)
|
||||
#else
|
||||
#ifndef major
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#include "../../Windows/FileFind.h"
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../Common/Defs.h"
|
||||
#endif
|
||||
@@ -44,15 +49,15 @@ static inline HRESULT ConvertBoolToHRESULT(bool result)
|
||||
}
|
||||
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
static const UInt32 kClusterSize = 1 << 18;
|
||||
#endif
|
||||
|
||||
CInFileStream::CInFileStream():
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
VirtPos(0),
|
||||
PhyPos(0),
|
||||
Buf(0),
|
||||
Buf(NULL),
|
||||
BufSize(0),
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
@@ -70,7 +75,7 @@ CInFileStream::CInFileStream():
|
||||
|
||||
CInFileStream::~CInFileStream()
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
MidFree(Buf);
|
||||
#endif
|
||||
|
||||
@@ -78,11 +83,11 @@ CInFileStream::~CInFileStream()
|
||||
Callback->InFileStream_On_Destroy(this, CallbackRef);
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
@@ -93,7 +98,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (VirtPos >= File.Size)
|
||||
return VirtPos == File.Size ? S_OK : E_FAIL;
|
||||
UInt64 rem = File.Size - VirtPos;
|
||||
const UInt64 rem = File.Size - VirtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
@@ -101,13 +106,13 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
const UInt32 mask = kClusterSize - 1;
|
||||
const UInt64 mask2 = ~(UInt64)mask;
|
||||
UInt64 alignedPos = VirtPos & mask2;
|
||||
const UInt64 alignedPos = VirtPos & mask2;
|
||||
if (BufSize > 0 && BufStartPos == alignedPos)
|
||||
{
|
||||
UInt32 pos = (UInt32)VirtPos & mask;
|
||||
const UInt32 pos = (UInt32)VirtPos & mask;
|
||||
if (pos >= BufSize)
|
||||
return S_OK;
|
||||
UInt32 rem = MyMin(BufSize - pos, size);
|
||||
const UInt32 rem = MyMin(BufSize - pos, size);
|
||||
memcpy(data, Buf + pos, rem);
|
||||
VirtPos += rem;
|
||||
if (processedSize)
|
||||
@@ -116,7 +121,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
|
||||
bool useBuf = false;
|
||||
if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
|
||||
if ((VirtPos & mask) != 0 || ((size_t)(ptrdiff_t)data & mask) != 0 )
|
||||
useBuf = true;
|
||||
else
|
||||
{
|
||||
@@ -135,7 +140,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (alignedPos != PhyPos)
|
||||
{
|
||||
UInt64 realNewPosition;
|
||||
bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition);
|
||||
const bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
PhyPos = realNewPosition;
|
||||
@@ -152,7 +157,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (!Buf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
bool result = File.Read1(Buf, readSize, BufSize);
|
||||
const bool result = File.Read1(Buf, readSize, BufSize);
|
||||
if (!result)
|
||||
return ConvertBoolToHRESULT(result);
|
||||
|
||||
@@ -177,7 +182,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
VirtPos += realProcessedSize;
|
||||
PhyPos += realProcessedSize;
|
||||
#endif
|
||||
@@ -185,7 +190,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (result)
|
||||
return S_OK;
|
||||
|
||||
#else // USE_WIN_FILE
|
||||
#else // Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -196,7 +201,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
*processedSize = (UInt32)res;
|
||||
return S_OK;
|
||||
}
|
||||
#endif // USE_WIN_FILE
|
||||
#endif // Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
{
|
||||
const DWORD error = ::GetLastError();
|
||||
@@ -209,7 +214,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
|
||||
#ifdef UNDER_CE
|
||||
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
size_t s2 = fread(data, 1, size, stdin);
|
||||
int error = ferror(stdin);
|
||||
@@ -220,7 +225,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi
|
||||
return E_FAIL;
|
||||
}
|
||||
#else
|
||||
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -256,14 +261,14 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
if (seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
@@ -290,7 +295,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
|
||||
in case of error. So we don't need additional code below */
|
||||
// if (!result) { realNewPosition = 0; File.GetPosition(realNewPosition); }
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
PhyPos = VirtPos = realNewPosition;
|
||||
#endif
|
||||
|
||||
@@ -316,17 +321,19 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
|
||||
Z7_COM7F_IMF(CInFileStream::GetSize(UInt64 *size))
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.GetLength(*size));
|
||||
}
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)
|
||||
Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))
|
||||
{
|
||||
if (!_info_WasLoaded)
|
||||
RINOK(ReloadProps());
|
||||
{
|
||||
RINOK(ReloadProps())
|
||||
}
|
||||
const BY_HANDLE_FILE_INFORMATION &info = _info;
|
||||
/*
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
@@ -343,10 +350,12 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
|
||||
Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props))
|
||||
{
|
||||
if (!_info_WasLoaded)
|
||||
RINOK(ReloadProps());
|
||||
{
|
||||
RINOK(ReloadProps())
|
||||
}
|
||||
const BY_HANDLE_FILE_INFORMATION &info = _info;
|
||||
/*
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
@@ -367,17 +376,19 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
if (!_info_WasLoaded)
|
||||
RINOK(ReloadProps());
|
||||
{
|
||||
RINOK(ReloadProps())
|
||||
}
|
||||
|
||||
if (!_info_WasLoaded)
|
||||
return S_OK;
|
||||
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
if (File.IsDeviceFile)
|
||||
{
|
||||
switch (propID)
|
||||
@@ -433,9 +444,9 @@ STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CInFileStream::ReloadProps()
|
||||
Z7_COM7F_IMF(CInFileStream::ReloadProps())
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
if (File.IsDeviceFile)
|
||||
{
|
||||
memset(&_info, 0, sizeof(_info));
|
||||
@@ -458,10 +469,12 @@ STDMETHODIMP CInFileStream::ReloadProps()
|
||||
|
||||
#elif !defined(_WIN32)
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)
|
||||
Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))
|
||||
{
|
||||
if (!_info_WasLoaded)
|
||||
RINOK(ReloadProps());
|
||||
{
|
||||
RINOK(ReloadProps())
|
||||
}
|
||||
const struct stat &st = _info;
|
||||
/*
|
||||
struct stat st;
|
||||
@@ -480,10 +493,12 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
|
||||
Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props))
|
||||
{
|
||||
if (!_info_WasLoaded)
|
||||
RINOK(ReloadProps());
|
||||
{
|
||||
RINOK(ReloadProps())
|
||||
}
|
||||
const struct stat &st = _info;
|
||||
/*
|
||||
struct stat st;
|
||||
@@ -518,10 +533,12 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))
|
||||
{
|
||||
if (!_info_WasLoaded)
|
||||
RINOK(ReloadProps());
|
||||
{
|
||||
RINOK(ReloadProps())
|
||||
}
|
||||
|
||||
if (!_info_WasLoaded)
|
||||
return S_OK;
|
||||
@@ -541,6 +558,11 @@ STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidMTime: PropVariant_SetFrom_FiTime(prop, ST_MTIME(st)); break;
|
||||
case kpidPosixAttrib: prop = (UInt32)st.st_mode; break;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
case kpidDeviceMajor:
|
||||
{
|
||||
// printf("\nst.st_rdev = %d\n", st.st_rdev);
|
||||
@@ -560,6 +582,10 @@ STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
// prop = (UInt32)123456789; // for debug
|
||||
break;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/*
|
||||
case kpidDevice:
|
||||
if (S_ISCHR(st.st_mode) ||
|
||||
@@ -629,7 +655,7 @@ STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CInFileStream::ReloadProps()
|
||||
Z7_COM7F_IMF(CInFileStream::ReloadProps())
|
||||
{
|
||||
_info_WasLoaded = (File.my_fstat(&_info) == 0);
|
||||
if (!_info_WasLoaded)
|
||||
@@ -650,9 +676,9 @@ HRESULT COutFileStream::Close()
|
||||
return ConvertBoolToHRESULT(File.Close());
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
const bool result = File.Write(data, size, realProcessedSize);
|
||||
@@ -677,12 +703,12 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
if (seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
UInt64 realNewPosition = 0;
|
||||
const bool result = File.Seek(offset, seekOrigin, realNewPosition);
|
||||
@@ -702,7 +728,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
|
||||
Z7_COM7F_IMF(COutFileStream::SetSize(UInt64 newSize))
|
||||
{
|
||||
return ConvertBoolToHRESULT(File.SetLength_KeepPosition(newSize));
|
||||
}
|
||||
@@ -714,7 +740,7 @@ HRESULT COutFileStream::GetSize(UInt64 *size)
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
size_t s2 = fwrite(data, 1, size, stdout);
|
||||
if (processedSize)
|
||||
@@ -724,7 +750,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro
|
||||
|
||||
#else
|
||||
|
||||
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// FileStreams.h
|
||||
|
||||
#ifndef __FILE_STREAMS_H
|
||||
#define __FILE_STREAMS_H
|
||||
#ifndef ZIP7_INC_FILE_STREAMS_H
|
||||
#define ZIP7_INC_FILE_STREAMS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WIN_FILE
|
||||
#define Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
#endif
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
@@ -18,13 +18,27 @@
|
||||
|
||||
|
||||
class CInFileStream;
|
||||
struct IInFileStream_Callback
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
DECLARE_INTERFACE(IInFileStream_Callback)
|
||||
{
|
||||
virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0;
|
||||
virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) = 0;
|
||||
};
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
class CInFileStream:
|
||||
|
||||
/*
|
||||
Z7_CLASS_IMP_COM_5(
|
||||
CInFileStream
|
||||
, IInStream
|
||||
, IStreamGetSize
|
||||
, IStreamGetProps
|
||||
, IStreamGetProps2
|
||||
, IStreamGetProp
|
||||
)
|
||||
*/
|
||||
Z7_class_final(CInFileStream) :
|
||||
public IInStream,
|
||||
public IStreamGetSize,
|
||||
public IStreamGetProps,
|
||||
@@ -32,12 +46,30 @@ class CInFileStream:
|
||||
public IStreamGetProp,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_UNKNOWN_IMP_5(
|
||||
IInStream,
|
||||
IStreamGetSize,
|
||||
IStreamGetProps,
|
||||
IStreamGetProps2,
|
||||
IStreamGetProp)
|
||||
|
||||
Z7_IFACE_COM7_IMP(ISequentialInStream)
|
||||
Z7_IFACE_COM7_IMP(IInStream)
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(IStreamGetSize)
|
||||
private:
|
||||
Z7_IFACE_COM7_IMP(IStreamGetProps)
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(IStreamGetProps2)
|
||||
Z7_IFACE_COM7_IMP(IStreamGetProp)
|
||||
|
||||
private:
|
||||
NWindows::NFile::NIO::CInFile File;
|
||||
public:
|
||||
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#ifdef Z7_DEVICE_FILE
|
||||
UInt64 VirtPos;
|
||||
UInt64 PhyPos;
|
||||
UInt64 BufStartPos;
|
||||
@@ -64,9 +96,8 @@ public:
|
||||
IInFileStream_Callback *Callback;
|
||||
UINT_PTR CallbackRef;
|
||||
|
||||
virtual ~CInFileStream();
|
||||
|
||||
CInFileStream();
|
||||
~CInFileStream();
|
||||
|
||||
void Set_PreserveATime(bool v)
|
||||
{
|
||||
@@ -89,44 +120,25 @@ public:
|
||||
_info_WasLoaded = false;
|
||||
return File.OpenShared(fileName, shareForWrite);
|
||||
}
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(IInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetSize)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProps2)
|
||||
MY_QUERYINTERFACE_ENTRY(IStreamGetProp)
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
STDMETHOD(GetSize)(UInt64 *size);
|
||||
STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib);
|
||||
STDMETHOD(GetProps2)(CStreamFileProps *props);
|
||||
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(ReloadProps)();
|
||||
};
|
||||
|
||||
class CStdInFileStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
virtual ~CStdInFileStream() {}
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CStdInFileStream
|
||||
, ISequentialInStream
|
||||
)
|
||||
};
|
||||
|
||||
class COutFileStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
COutFileStream
|
||||
, IOutStream
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
public:
|
||||
|
||||
NWindows::NFile::NIO::COutFile File;
|
||||
|
||||
virtual ~COutFileStream() {}
|
||||
bool Create(CFSTR fileName, bool createAlways)
|
||||
{
|
||||
ProcessedSize = 0;
|
||||
@@ -148,15 +160,9 @@ public:
|
||||
}
|
||||
bool SetMTime(const CFiTime *mTime) { return File.SetMTime(mTime); }
|
||||
|
||||
MY_UNKNOWN_IMP1(IOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
|
||||
bool SeekToBegin_bool()
|
||||
{
|
||||
#ifdef USE_WIN_FILE
|
||||
#ifdef Z7_FILE_STREAMS_USE_WIN_FILE
|
||||
return File.SeekToBegin();
|
||||
#else
|
||||
return File.seekToBegin() == 0;
|
||||
@@ -166,18 +172,15 @@ public:
|
||||
HRESULT GetSize(UInt64 *size);
|
||||
};
|
||||
|
||||
class CStdOutFileStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CStdOutFileStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
UInt64 _size;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
UInt64 GetSize() const { return _size; }
|
||||
CStdOutFileStream(): _size(0) {}
|
||||
virtual ~CStdOutFileStream() {}
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "FilterCoder.h"
|
||||
@@ -33,13 +35,17 @@ void CAlignedMidBuffer::AllocAligned(size_t size)
|
||||
|
||||
Some filters (BCJ and others) don't process data at the end of stream in some cases.
|
||||
So the encoder and decoder write such last bytes without change.
|
||||
|
||||
Most filters process all data, if we send aligned size to filter.
|
||||
But BCJ filter can process up 4 bytes less than sent size.
|
||||
And ARMT filter can process 2 bytes less than sent size.
|
||||
*/
|
||||
|
||||
|
||||
static const UInt32 kBufSize = 1 << 20;
|
||||
static const UInt32 kBufSize = 1 << 21;
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
|
||||
STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
|
||||
Z7_COM7F_IMF(CFilterCoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; }
|
||||
Z7_COM7F_IMF(CFilterCoder::SetOutBufSize(UInt32 , UInt32 size)) { _outBufSize = size; return S_OK; }
|
||||
|
||||
HRESULT CFilterCoder::Alloc()
|
||||
{
|
||||
@@ -51,6 +57,7 @@ HRESULT CFilterCoder::Alloc()
|
||||
size &= ~(UInt32)(kMinSize - 1);
|
||||
if (size < kMinSize)
|
||||
size = kMinSize;
|
||||
// size = (1 << 12); // + 117; // for debug
|
||||
if (!_buf || _bufSize != size)
|
||||
{
|
||||
AllocAligned(size);
|
||||
@@ -63,7 +70,7 @@ HRESULT CFilterCoder::Alloc()
|
||||
|
||||
HRESULT CFilterCoder::Init_and_Alloc()
|
||||
{
|
||||
RINOK(Filter->Init());
|
||||
RINOK(Filter->Init())
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
@@ -72,78 +79,197 @@ CFilterCoder::CFilterCoder(bool encodeMode):
|
||||
_inBufSize(kBufSize),
|
||||
_outBufSize(kBufSize),
|
||||
_encodeMode(encodeMode),
|
||||
_outSizeIsDefined(false),
|
||||
_outSize_Defined(false),
|
||||
_outSize(0),
|
||||
_nowPos64(0)
|
||||
{}
|
||||
|
||||
CFilterCoder::~CFilterCoder()
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
Z7_COM7F_IMF(CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))
|
||||
{
|
||||
RINOK(Init_and_Alloc());
|
||||
|
||||
RINOK(Init_and_Alloc())
|
||||
|
||||
/*
|
||||
It's expected that BCJ/ARMT filter can process up to 4 bytes less
|
||||
than sent data size. For such BCJ/ARMT cases with non-filtered data we:
|
||||
- write some filtered data to output stream
|
||||
- move non-written data (filtered and non-filtered data) to start of buffer
|
||||
- read more new data from input stream to position after end of non-filtered data
|
||||
- call Filter() for concatenated data in buffer.
|
||||
|
||||
For all cases, even for cases with partial filtering (BCJ/ARMT),
|
||||
we try to keep real/virtual alignment for all operations
|
||||
(memmove, Read(), Filter(), Write()).
|
||||
We use (kAlignSize=64) alignmnent that is larger than (16-bytes)
|
||||
required for AES filter alignment.
|
||||
|
||||
AES-CBC uses 16-bytes blocks, that is simple case for processing here,
|
||||
if we call Filter() for aligned size for all calls except of last call (last block).
|
||||
And now there are no filters that use blocks with non-power2 size,
|
||||
but we try to support such non-power2 filters too here at Code().
|
||||
*/
|
||||
|
||||
UInt64 prev = 0;
|
||||
UInt64 nowPos64 = 0;
|
||||
bool inputFinished = false;
|
||||
UInt32 pos = 0;
|
||||
UInt32 readPos = 0;
|
||||
UInt32 filterPos = 0;
|
||||
|
||||
while (!outSize || nowPos64 < *outSize)
|
||||
{
|
||||
HRESULT hres = S_OK;
|
||||
if (!inputFinished)
|
||||
{
|
||||
size_t processedSize = _bufSize - pos;
|
||||
RINOK(ReadStream(inStream, _buf + pos, &processedSize));
|
||||
pos += (UInt32)processedSize;
|
||||
inputFinished = (pos != _bufSize);
|
||||
size_t processedSize = _bufSize - readPos;
|
||||
/* for AES filters we need at least max(16, kAlignSize) bytes in buffer.
|
||||
But we try to read full buffer to reduce the number of Filter() and Write() calls.
|
||||
*/
|
||||
hres = ReadStream(inStream, _buf + readPos, &processedSize);
|
||||
readPos += (UInt32)processedSize;
|
||||
inputFinished = (readPos != _bufSize);
|
||||
if (hres != S_OK)
|
||||
{
|
||||
// do we need to stop encoding after reading error?
|
||||
// if (_encodeMode) return hres;
|
||||
inputFinished = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == 0)
|
||||
return S_OK;
|
||||
if (readPos == 0)
|
||||
return hres;
|
||||
|
||||
UInt32 filtered = Filter->Filter(_buf, pos);
|
||||
|
||||
if (filtered > pos)
|
||||
/* we set (needMoreInput = true), if it's block-filter (like AES-CBC)
|
||||
that needs more data for current block filtering:
|
||||
We read full input buffer with Read(), and _bufSize is aligned,
|
||||
So the possible cases when we set (needMoreInput = true) are:
|
||||
1) decode : filter needs more data after the end of input stream.
|
||||
another cases are possible for non-power2-block-filter,
|
||||
because buffer size is not aligned for filter_non_power2_block_size:
|
||||
2) decode/encode : filter needs more data from non-finished input stream
|
||||
3) encode : filter needs more space for zeros after the end of input stream
|
||||
*/
|
||||
bool needMoreInput = false;
|
||||
|
||||
while (readPos != filterPos)
|
||||
{
|
||||
// AES
|
||||
if (!inputFinished || filtered > _bufSize)
|
||||
return E_FAIL;
|
||||
/* Filter() is allowed to process part of data.
|
||||
Here we use the loop to filter as max as possible.
|
||||
when we call Filter(data, size):
|
||||
if (size < 16), AES-CTR filter uses internal 16-byte buffer.
|
||||
new (since v23.00) AES-CTR filter allows (size < 16) for non-last block,
|
||||
but it will work less efficiently than calls with aligned (size).
|
||||
We still support old (before v23.00) AES-CTR filters here.
|
||||
We have aligned (size) for AES-CTR, if it's not last block.
|
||||
We have aligned (readPos) for any filter, if (!inputFinished).
|
||||
We also meet the requirements for (data) pointer in Filter() call:
|
||||
{
|
||||
(virtual_stream_offset % aligment_size) == (data_ptr % aligment_size)
|
||||
(aligment_size == 2^N)
|
||||
(aligment_size >= 16)
|
||||
}
|
||||
*/
|
||||
const UInt32 cur = Filter->Filter(_buf + filterPos, readPos - filterPos);
|
||||
if (cur == 0)
|
||||
break;
|
||||
const UInt32 f = filterPos + cur;
|
||||
if (cur > readPos - filterPos)
|
||||
{
|
||||
// AES-CBC
|
||||
if (hres != S_OK)
|
||||
break;
|
||||
|
||||
if (!_encodeMode
|
||||
|| cur > _bufSize - filterPos
|
||||
|| !inputFinished)
|
||||
{
|
||||
/* (cur > _bufSize - filterPos) is unexpected for AES filter, if _bufSize is multiply of 16.
|
||||
But we support this case, if some future filter will use block with non-power2-size.
|
||||
*/
|
||||
needMoreInput = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* (_encodeMode && inputFinished).
|
||||
We add zero bytes as pad in current block after the end of read data. */
|
||||
Byte *buf = _buf;
|
||||
do
|
||||
buf[readPos] = 0;
|
||||
while (++readPos != f);
|
||||
// (readPos) now is (size_of_real_input_data + size_of_zero_pad)
|
||||
if (cur != Filter->Filter(buf + filterPos, cur))
|
||||
return E_FAIL;
|
||||
}
|
||||
filterPos = f;
|
||||
}
|
||||
|
||||
UInt32 size = filterPos;
|
||||
if (hres == S_OK)
|
||||
{
|
||||
/* If we need more Read() or Filter() calls, then we need to Write()
|
||||
some data and move unwritten data to get additional space in buffer.
|
||||
We try to keep alignment for data moves, Read(), Filter() and Write() calls.
|
||||
*/
|
||||
const UInt32 kAlignSize = 1 << 6;
|
||||
const UInt32 alignedFiltered = filterPos & ~(kAlignSize - 1);
|
||||
if (inputFinished)
|
||||
{
|
||||
if (!needMoreInput)
|
||||
size = readPos; // for risc/bcj filters in last block we write data after filterPos.
|
||||
else if (_encodeMode)
|
||||
size = alignedFiltered; // for non-power2-block-encode-filter
|
||||
}
|
||||
else
|
||||
size = alignedFiltered;
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 writeSize = size;
|
||||
if (outSize)
|
||||
{
|
||||
const UInt64 rem = *outSize - nowPos64;
|
||||
if (writeSize > rem)
|
||||
writeSize = (UInt32)rem;
|
||||
}
|
||||
RINOK(WriteStream(outStream, _buf, writeSize))
|
||||
nowPos64 += writeSize;
|
||||
}
|
||||
|
||||
if (hres != S_OK)
|
||||
return hres;
|
||||
|
||||
if (inputFinished)
|
||||
{
|
||||
if (readPos == size)
|
||||
return hres;
|
||||
if (!_encodeMode)
|
||||
{
|
||||
// block-decode-filter (AES-CBS) has non-full last block
|
||||
// we don't want unaligned data move for more iterations with this error case.
|
||||
return S_FALSE;
|
||||
|
||||
Byte *buf = _buf;
|
||||
do
|
||||
buf[pos] = 0;
|
||||
while (++pos != filtered);
|
||||
|
||||
if (filtered != Filter->Filter(buf, filtered))
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 size = (filtered != 0 ? filtered : pos);
|
||||
if (outSize)
|
||||
if (size == 0)
|
||||
{
|
||||
const UInt64 remSize = *outSize - nowPos64;
|
||||
if (size > remSize)
|
||||
size = (UInt32)remSize;
|
||||
// it's unexpected that we have no any move in this iteration.
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
RINOK(WriteStream(outStream, _buf, size));
|
||||
nowPos64 += size;
|
||||
|
||||
if (filtered == 0)
|
||||
return S_OK;
|
||||
pos -= filtered;
|
||||
for (UInt32 i = 0; i < pos; i++)
|
||||
_buf[i] = _buf[filtered++];
|
||||
// if (size != 0)
|
||||
{
|
||||
if (filterPos < size)
|
||||
return E_FAIL; // filterPos = 0; else
|
||||
filterPos -= size;
|
||||
readPos -= size;
|
||||
if (readPos != 0)
|
||||
memmove(_buf, _buf + size, readPos);
|
||||
}
|
||||
// printf("\nnowPos64=%x, readPos=%x, filterPos=%x\n", (unsigned)nowPos64, (unsigned)readPos, (unsigned)filterPos);
|
||||
|
||||
if (progress && (nowPos64 - prev) >= (1 << 22))
|
||||
{
|
||||
prev = nowPos64;
|
||||
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
|
||||
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,13 +280,13 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStr
|
||||
|
||||
// ---------- Write to Filter ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
|
||||
Z7_COM7F_IMF(CFilterCoder::SetOutStream(ISequentialOutStream *outStream))
|
||||
{
|
||||
_outStream = outStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseOutStream()
|
||||
Z7_COM7F_IMF(CFilterCoder::ReleaseOutStream())
|
||||
{
|
||||
_outStream.Release();
|
||||
return S_OK;
|
||||
@@ -171,9 +297,9 @@ HRESULT CFilterCoder::Flush2()
|
||||
while (_convSize != 0)
|
||||
{
|
||||
UInt32 num = _convSize;
|
||||
if (_outSizeIsDefined)
|
||||
if (_outSize_Defined)
|
||||
{
|
||||
UInt64 rem = _outSize - _nowPos64;
|
||||
const UInt64 rem = _outSize - _nowPos64;
|
||||
if (num > rem)
|
||||
num = (UInt32)rem;
|
||||
if (num == 0)
|
||||
@@ -181,21 +307,23 @@ HRESULT CFilterCoder::Flush2()
|
||||
}
|
||||
|
||||
UInt32 processed = 0;
|
||||
HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);
|
||||
const HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);
|
||||
if (processed == 0)
|
||||
return res != S_OK ? res : E_FAIL;
|
||||
|
||||
_convPos += processed;
|
||||
_convSize -= processed;
|
||||
_nowPos64 += processed;
|
||||
RINOK(res);
|
||||
RINOK(res)
|
||||
}
|
||||
|
||||
if (_convPos != 0)
|
||||
const UInt32 convPos = _convPos;
|
||||
if (convPos != 0)
|
||||
{
|
||||
UInt32 num = _bufPos - _convPos;
|
||||
const UInt32 num = _bufPos - convPos;
|
||||
Byte *buf = _buf;
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
_buf[i] = _buf[_convPos + i];
|
||||
buf[i] = buf[convPos + i];
|
||||
_bufPos = num;
|
||||
_convPos = 0;
|
||||
}
|
||||
@@ -203,14 +331,14 @@ HRESULT CFilterCoder::Flush2()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
RINOK(Flush2());
|
||||
RINOK(Flush2())
|
||||
|
||||
// _convSize is 0
|
||||
// _convPos is 0
|
||||
@@ -245,20 +373,22 @@ STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processe
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::OutStreamFinish()
|
||||
Z7_COM7F_IMF(CFilterCoder::OutStreamFinish())
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
RINOK(Flush2());
|
||||
RINOK(Flush2())
|
||||
if (_bufPos == 0)
|
||||
break;
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
if (_convSize == 0)
|
||||
_convSize = _bufPos;
|
||||
else if (_convSize > _bufPos)
|
||||
const UInt32 convSize = Filter->Filter(_buf, _bufPos);
|
||||
_convSize = convSize;
|
||||
UInt32 bufPos = _bufPos;
|
||||
if (convSize == 0)
|
||||
_convSize = bufPos;
|
||||
else if (convSize > bufPos)
|
||||
{
|
||||
// AES
|
||||
if (_convSize > _bufSize)
|
||||
if (convSize > _bufSize)
|
||||
{
|
||||
_convSize = 0;
|
||||
return E_FAIL;
|
||||
@@ -268,9 +398,11 @@ STDMETHODIMP CFilterCoder::OutStreamFinish()
|
||||
_convSize = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
for (; _bufPos < _convSize; _bufPos++)
|
||||
_buf[_bufPos] = 0;
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
Byte *buf = _buf;
|
||||
for (; bufPos < convSize; bufPos++)
|
||||
buf[bufPos] = 0;
|
||||
_bufPos = bufPos;
|
||||
_convSize = Filter->Filter(_buf, bufPos);
|
||||
if (_convSize != _bufPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
@@ -285,7 +417,7 @@ STDMETHODIMP CFilterCoder::OutStreamFinish()
|
||||
|
||||
// ---------- Init functions ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::InitEncoder()
|
||||
Z7_COM7F_IMF(CFilterCoder::InitEncoder())
|
||||
{
|
||||
InitSpecVars();
|
||||
return Init_and_Alloc();
|
||||
@@ -297,33 +429,33 @@ HRESULT CFilterCoder::Init_NoSubFilterInit()
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
Z7_COM7F_IMF(CFilterCoder::SetOutStreamSize(const UInt64 *outSize))
|
||||
{
|
||||
InitSpecVars();
|
||||
if (outSize)
|
||||
{
|
||||
_outSize = *outSize;
|
||||
_outSizeIsDefined = true;
|
||||
_outSize_Defined = true;
|
||||
}
|
||||
return Init_and_Alloc();
|
||||
}
|
||||
|
||||
// ---------- Read from Filter ----------
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
|
||||
Z7_COM7F_IMF(CFilterCoder::SetInStream(ISequentialInStream *inStream))
|
||||
{
|
||||
_inStream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReleaseInStream()
|
||||
Z7_COM7F_IMF(CFilterCoder::ReleaseInStream())
|
||||
{
|
||||
_inStream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -334,9 +466,9 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (size > _convSize)
|
||||
size = _convSize;
|
||||
if (_outSizeIsDefined)
|
||||
if (_outSize_Defined)
|
||||
{
|
||||
UInt64 rem = _outSize - _nowPos64;
|
||||
const UInt64 rem = _outSize - _nowPos64;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
@@ -349,46 +481,51 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_convPos != 0)
|
||||
const UInt32 convPos = _convPos;
|
||||
if (convPos != 0)
|
||||
{
|
||||
UInt32 num = _bufPos - _convPos;
|
||||
const UInt32 num = _bufPos - convPos;
|
||||
Byte *buf = _buf;
|
||||
for (UInt32 i = 0; i < num; i++)
|
||||
_buf[i] = _buf[_convPos + i];
|
||||
buf[i] = buf[convPos + i];
|
||||
_bufPos = num;
|
||||
_convPos = 0;
|
||||
}
|
||||
|
||||
{
|
||||
size_t readSize = _bufSize - _bufPos;
|
||||
HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);
|
||||
const HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);
|
||||
_bufPos += (UInt32)readSize;
|
||||
RINOK(res);
|
||||
RINOK(res)
|
||||
}
|
||||
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
const UInt32 convSize = Filter->Filter(_buf, _bufPos);
|
||||
_convSize = convSize;
|
||||
|
||||
if (_convSize == 0)
|
||||
UInt32 bufPos = _bufPos;
|
||||
|
||||
if (convSize == 0)
|
||||
{
|
||||
if (_bufPos == 0)
|
||||
if (bufPos == 0)
|
||||
break;
|
||||
// BCJ
|
||||
_convSize = _bufPos;
|
||||
_convSize = bufPos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_convSize > _bufPos)
|
||||
if (convSize > bufPos)
|
||||
{
|
||||
// AES
|
||||
if (_convSize > _bufSize)
|
||||
if (convSize > _bufSize)
|
||||
return E_FAIL;
|
||||
if (!_encodeMode)
|
||||
return S_FALSE;
|
||||
|
||||
Byte *buf = _buf;
|
||||
do
|
||||
_buf[_bufPos] = 0;
|
||||
while (++_bufPos != _convSize);
|
||||
|
||||
_convSize = Filter->Filter(_buf, _convSize);
|
||||
buf[bufPos] = 0;
|
||||
while (++bufPos != convSize);
|
||||
_bufPos = bufPos;
|
||||
_convSize = Filter->Filter(_buf, convSize);
|
||||
if (_convSize != _bufPos)
|
||||
return E_FAIL;
|
||||
}
|
||||
@@ -398,39 +535,43 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
|
||||
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{ return _SetPassword->CryptoSetPassword(data, size); }
|
||||
Z7_COM7F_IMF(CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size))
|
||||
{ return _setPassword->CryptoSetPassword(data, size); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)
|
||||
{ return _CryptoProperties->SetKey(data, size); }
|
||||
Z7_COM7F_IMF(CFilterCoder::SetKey(const Byte *data, UInt32 size))
|
||||
{ return _cryptoProperties->SetKey(data, size); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size)
|
||||
{ return _CryptoProperties->SetInitVector(data, size); }
|
||||
Z7_COM7F_IMF(CFilterCoder::SetInitVector(const Byte *data, UInt32 size))
|
||||
{ return _cryptoProperties->SetInitVector(data, size); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties)
|
||||
{ return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }
|
||||
Z7_COM7F_IMF(CFilterCoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties))
|
||||
{ return _setCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }
|
||||
|
||||
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{ return _WriteCoderProperties->WriteCoderProperties(outStream); }
|
||||
Z7_COM7F_IMF(CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream))
|
||||
{ return _writeCoderProperties->WriteCoderProperties(outStream); }
|
||||
|
||||
Z7_COM7F_IMF(CFilterCoder::SetCoderPropertiesOpt(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties))
|
||||
{ return _setCoderPropertiesOpt->SetCoderPropertiesOpt(propIDs, properties, numProperties); }
|
||||
|
||||
/*
|
||||
STDMETHODIMP CFilterCoder::ResetSalt()
|
||||
{ return _CryptoResetSalt->ResetSalt(); }
|
||||
Z7_COM7F_IMF(CFilterCoder::ResetSalt()
|
||||
{ return _cryptoResetSalt->ResetSalt(); }
|
||||
*/
|
||||
|
||||
STDMETHODIMP CFilterCoder::ResetInitVector()
|
||||
{ return _CryptoResetInitVector->ResetInitVector(); }
|
||||
Z7_COM7F_IMF(CFilterCoder::ResetInitVector())
|
||||
{ return _cryptoResetInitVector->ResetInitVector(); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{ return _SetDecoderProperties2->SetDecoderProperties2(data, size); }
|
||||
Z7_COM7F_IMF(CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size))
|
||||
{ return _setDecoderProperties2->SetDecoderProperties2(data, size); }
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// FilterCoder.h
|
||||
|
||||
#ifndef __FILTER_CODER_H
|
||||
#define __FILTER_CODER_H
|
||||
#ifndef ZIP7_INC_FILTER_CODER_H
|
||||
#define ZIP7_INC_FILTER_CODER_H
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../ICoder.h"
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
#include "../IPassword.h"
|
||||
#endif
|
||||
|
||||
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \
|
||||
#define Z7_COM_QI_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \
|
||||
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
|
||||
*outObject = (void *)(i *)this; }
|
||||
|
||||
@@ -26,7 +26,8 @@ struct CAlignedMidBuffer
|
||||
void AllocAligned(size_t size);
|
||||
};
|
||||
|
||||
class CFilterCoder:
|
||||
|
||||
class CFilterCoder Z7_final :
|
||||
public ICompressCoder,
|
||||
|
||||
public ICompressSetOutStreamSize,
|
||||
@@ -41,14 +42,15 @@ class CFilterCoder:
|
||||
|
||||
public ICompressSetBufSize,
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
public ICryptoSetPassword,
|
||||
public ICryptoProperties,
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressWriteCoderProperties,
|
||||
public ICompressSetCoderPropertiesOpt,
|
||||
// public ICryptoResetSalt,
|
||||
public ICryptoResetInitVector,
|
||||
#endif
|
||||
@@ -62,7 +64,7 @@ class CFilterCoder:
|
||||
UInt32 _outBufSize;
|
||||
|
||||
bool _encodeMode;
|
||||
bool _outSizeIsDefined;
|
||||
bool _outSize_Defined;
|
||||
UInt64 _outSize;
|
||||
UInt64 _nowPos64;
|
||||
|
||||
@@ -78,7 +80,7 @@ class CFilterCoder:
|
||||
_convPos = 0;
|
||||
_convSize = 0;
|
||||
|
||||
_outSizeIsDefined = false;
|
||||
_outSize_Defined = false;
|
||||
_outSize = 0;
|
||||
_nowPos64 = 0;
|
||||
}
|
||||
@@ -87,117 +89,111 @@ class CFilterCoder:
|
||||
HRESULT Init_and_Alloc();
|
||||
HRESULT Flush2();
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoSetPassword> _SetPassword;
|
||||
CMyComPtr<ICryptoProperties> _CryptoProperties;
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
CMyComPtr<ICryptoSetPassword> _setPassword;
|
||||
CMyComPtr<ICryptoProperties> _cryptoProperties;
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
|
||||
CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties;
|
||||
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
|
||||
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
CMyComPtr<ICompressSetCoderProperties> _setCoderProperties;
|
||||
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
|
||||
CMyComPtr<ICompressSetCoderPropertiesOpt> _setCoderPropertiesOpt;
|
||||
// CMyComPtr<ICryptoResetSalt> _cryptoResetSalt;
|
||||
CMyComPtr<ICryptoResetInitVector> _cryptoResetInitVector;
|
||||
#endif
|
||||
|
||||
CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2;
|
||||
CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties2;
|
||||
|
||||
public:
|
||||
CMyComPtr<ICompressFilter> Filter;
|
||||
|
||||
CFilterCoder(bool encodeMode);
|
||||
~CFilterCoder();
|
||||
|
||||
class C_InStream_Releaser
|
||||
struct C_InStream_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_InStream_Releaser(): FilterCoder(NULL) {}
|
||||
~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
|
||||
};
|
||||
|
||||
class C_OutStream_Releaser
|
||||
struct C_OutStream_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_OutStream_Releaser(): FilterCoder(NULL) {}
|
||||
~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
|
||||
};
|
||||
|
||||
class C_Filter_Releaser
|
||||
struct C_Filter_Releaser
|
||||
{
|
||||
public:
|
||||
CFilterCoder *FilterCoder;
|
||||
C_Filter_Releaser(): FilterCoder(NULL) {}
|
||||
~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); }
|
||||
};
|
||||
|
||||
private:
|
||||
Z7_COM_QI_BEGIN2(ICompressCoder)
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)
|
||||
Z7_COM_QI_ENTRY(ICompressInitEncoder)
|
||||
|
||||
Z7_COM_QI_ENTRY(ICompressSetInStream)
|
||||
Z7_COM_QI_ENTRY(ISequentialInStream)
|
||||
|
||||
Z7_COM_QI_ENTRY(ICompressSetOutStream)
|
||||
Z7_COM_QI_ENTRY(ISequentialOutStream)
|
||||
Z7_COM_QI_ENTRY(IOutStreamFinish)
|
||||
|
||||
Z7_COM_QI_ENTRY(ICompressSetBufSize)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
|
||||
MY_QUERYINTERFACE_ENTRY(IOutStreamFinish)
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties)
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
Z7_COM_QI_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
|
||||
Z7_COM_QI_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties)
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties)
|
||||
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
Z7_COM_QI_ENTRY_AG(ICompressSetCoderProperties, Filter, _setCoderProperties)
|
||||
Z7_COM_QI_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
|
||||
Z7_COM_QI_ENTRY_AG(ICompressSetCoderPropertiesOpt, Filter, _setCoderPropertiesOpt)
|
||||
// Z7_COM_QI_ENTRY_AG(ICryptoResetSalt, Filter, _cryptoResetSalt)
|
||||
Z7_COM_QI_ENTRY_AG(ICryptoResetInitVector, Filter, _cryptoResetInitVector)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2)
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
Z7_COM_QI_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties2)
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(ICompressCoder)
|
||||
Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)
|
||||
Z7_IFACE_COM7_IMP(ICompressInitEncoder)
|
||||
Z7_IFACE_COM7_IMP(ICompressSetInStream)
|
||||
private:
|
||||
Z7_IFACE_COM7_IMP(ISequentialInStream)
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(ICompressSetOutStream)
|
||||
private:
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(IOutStreamFinish)
|
||||
private:
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(InitEncoder)();
|
||||
Z7_IFACE_COM7_IMP(ICompressSetBufSize)
|
||||
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(ReleaseOutStream)();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(OutStreamFinish)();
|
||||
|
||||
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
|
||||
STDMETHOD(SetKey)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
Z7_IFACE_COM7_IMP(ICryptoSetPassword)
|
||||
Z7_IFACE_COM7_IMP(ICryptoProperties)
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
|
||||
const PROPVARIANT *properties, UInt32 numProperties);
|
||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
// STDMETHOD(ResetSalt)();
|
||||
STDMETHOD(ResetInitVector)();
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)
|
||||
Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties)
|
||||
Z7_IFACE_COM7_IMP(ICompressSetCoderPropertiesOpt)
|
||||
// Z7_IFACE_COM7_IMP(ICryptoResetSalt)
|
||||
Z7_IFACE_COM7_IMP(ICryptoResetInitVector)
|
||||
#endif
|
||||
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)
|
||||
|
||||
HRESULT Init_NoSubFilterInit();
|
||||
};
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#include "InBuffer.h"
|
||||
|
||||
CInBufferBase::CInBufferBase() throw():
|
||||
_buf(0),
|
||||
_bufLim(0),
|
||||
_bufBase(0),
|
||||
_stream(0),
|
||||
_buf(NULL),
|
||||
_bufLim(NULL),
|
||||
_bufBase(NULL),
|
||||
_stream(NULL),
|
||||
_processedSize(0),
|
||||
_bufSize(0),
|
||||
_wasFinished(false),
|
||||
@@ -22,18 +22,18 @@ bool CInBuffer::Create(size_t bufSize) throw()
|
||||
const unsigned kMinBlockSize = 1;
|
||||
if (bufSize < kMinBlockSize)
|
||||
bufSize = kMinBlockSize;
|
||||
if (_bufBase != 0 && _bufSize == bufSize)
|
||||
if (_bufBase != NULL && _bufSize == bufSize)
|
||||
return true;
|
||||
Free();
|
||||
_bufSize = bufSize;
|
||||
_bufBase = (Byte *)::MidAlloc(bufSize);
|
||||
return (_bufBase != 0);
|
||||
return (_bufBase != NULL);
|
||||
}
|
||||
|
||||
void CInBuffer::Free() throw()
|
||||
{
|
||||
::MidFree(_bufBase);
|
||||
_bufBase = 0;
|
||||
_bufBase = NULL;
|
||||
}
|
||||
|
||||
void CInBufferBase::Init() throw()
|
||||
@@ -42,7 +42,7 @@ void CInBufferBase::Init() throw()
|
||||
_buf = _bufBase;
|
||||
_bufLim = _buf;
|
||||
_wasFinished = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
NumExtraBytes = 0;
|
||||
@@ -50,7 +50,7 @@ void CInBufferBase::Init() throw()
|
||||
|
||||
bool CInBufferBase::ReadBlock()
|
||||
{
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
if (ErrorCode != S_OK)
|
||||
return false;
|
||||
#endif
|
||||
@@ -61,8 +61,8 @@ bool CInBufferBase::ReadBlock()
|
||||
_bufLim = _bufBase;
|
||||
UInt32 processed;
|
||||
// FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
|
||||
HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
const HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// InBuffer.h
|
||||
|
||||
#ifndef __IN_BUFFER_H
|
||||
#define __IN_BUFFER_H
|
||||
#ifndef ZIP7_INC_IN_BUFFER_H
|
||||
#define ZIP7_INC_IN_BUFFER_H
|
||||
|
||||
#include "../../Common/MyException.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
#ifndef Z7_NO_EXCEPTIONS
|
||||
struct CInBufferException: public CSystemException
|
||||
{
|
||||
CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
@@ -31,7 +31,7 @@ protected:
|
||||
Byte ReadByte_FromNewBlock();
|
||||
|
||||
public:
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
HRESULT ErrorCode;
|
||||
#endif
|
||||
UInt32 NumExtraBytes;
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
_buf = buf + pos;
|
||||
_bufLim = buf + end;
|
||||
_wasFinished = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
NumExtraBytes = 0;
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
void Init() throw();
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Z7_FORCE_INLINE
|
||||
bool ReadByte(Byte &b)
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Z7_FORCE_INLINE
|
||||
bool ReadByte_FromBuf(Byte &b)
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Z7_FORCE_INLINE
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (_buf >= _bufLim)
|
||||
|
||||
@@ -2,170 +2,236 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "InOutTempBuffer.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
static const size_t kTempBufSize = (1 << 20);
|
||||
|
||||
#define kTempFilePrefixString FTEXT("7zt")
|
||||
/*
|
||||
Total buffer size limit, if we use temp file scheme:
|
||||
32-bit: 16 MiB = 1 MiB * 16 buffers
|
||||
64-bit: 4 GiB = 1 MiB * 4096 buffers
|
||||
*/
|
||||
static const size_t kNumBufsMax = (size_t)1 << (sizeof(size_t) * 2 - 4);
|
||||
|
||||
#endif
|
||||
|
||||
static const size_t kBufSize = (size_t)1 << 20;
|
||||
|
||||
|
||||
CInOutTempBuffer::CInOutTempBuffer():
|
||||
_size(0),
|
||||
_bufs(NULL),
|
||||
_numBufs(0),
|
||||
_numFilled(0)
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
_tempFile_Created = false;
|
||||
_useMemOnly = false;
|
||||
_crc = CRC_INIT_VAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
CInOutTempBuffer::~CInOutTempBuffer()
|
||||
{
|
||||
delete []_buf;
|
||||
for (size_t i = 0; i < _numBufs; i++)
|
||||
MyFree(_bufs[i]);
|
||||
MyFree(_bufs);
|
||||
}
|
||||
#endif
|
||||
|
||||
CInOutTempBuffer::CInOutTempBuffer()
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
: _buf(NULL)
|
||||
#endif
|
||||
{ }
|
||||
|
||||
void CInOutTempBuffer::Create()
|
||||
void *CInOutTempBuffer::GetBuf(size_t index)
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
if (!_buf)
|
||||
_buf = new Byte[kTempBufSize];
|
||||
#endif
|
||||
if (index >= _numBufs)
|
||||
{
|
||||
const size_t num = (_numBufs == 0 ? 16 : _numBufs * 2);
|
||||
void **p = (void **)MyRealloc(_bufs, num * sizeof(void *));
|
||||
if (!p)
|
||||
return NULL;
|
||||
_bufs = p;
|
||||
memset(p + _numBufs, 0, (num - _numBufs) * sizeof(void *));
|
||||
_numBufs = num;
|
||||
}
|
||||
|
||||
void *buf = _bufs[index];
|
||||
if (!buf)
|
||||
{
|
||||
buf = MyAlloc(kBufSize);
|
||||
if (buf)
|
||||
_bufs[index] = buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void CInOutTempBuffer::InitWriting()
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
_bufPos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_tempFileCreated = false;
|
||||
#endif
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
|
||||
static inline HRESULT Get_HRESULT_LastError()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD lastError = ::GetLastError();
|
||||
if (lastError != 0)
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
#endif
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT CInOutTempBuffer::Write_HRESULT(const void *data, UInt32 size)
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
size_t cur = kTempBufSize - _bufPos;
|
||||
if (cur != 0)
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
if (!_tempFile_Created)
|
||||
#endif
|
||||
for (;;) // loop for additional attemp to allocate memory after file creation error
|
||||
{
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memcpy(_buf + _bufPos, data, cur);
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
_bufPos += cur;
|
||||
_size += cur;
|
||||
size -= (UInt32)cur;
|
||||
data = ((const Byte *)data) + cur;
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
bool allocError = false;
|
||||
#endif
|
||||
|
||||
for (;;) // loop for writing to buffers
|
||||
{
|
||||
const size_t index = (size_t)(_size / kBufSize);
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
if (index >= kNumBufsMax && !_useMemOnly)
|
||||
break;
|
||||
#endif
|
||||
|
||||
void *buf = GetBuf(index);
|
||||
if (!buf)
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
if (!_useMemOnly)
|
||||
{
|
||||
allocError = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
const size_t offset = (size_t)(_size) & (kBufSize - 1);
|
||||
size_t cur = kBufSize - offset;
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memcpy((Byte *)buf + offset, data, cur);
|
||||
_size += cur;
|
||||
if (index >= _numFilled)
|
||||
_numFilled = index + 1;
|
||||
data = (const void *)((const Byte *)data + cur);
|
||||
size -= (UInt32)cur;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
#ifndef _WIN32
|
||||
_outFile.mode_for_Create = 0600; // only owner will have the rights to access this file
|
||||
#endif
|
||||
if (_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
|
||||
{
|
||||
_tempFile_Created = true;
|
||||
break;
|
||||
}
|
||||
_useMemOnly = true;
|
||||
if (allocError)
|
||||
return GetLastError_noZero_HRESULT();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (!_tempFileCreated)
|
||||
{
|
||||
if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
|
||||
return Get_HRESULT_LastError();
|
||||
_tempFileCreated = true;
|
||||
}
|
||||
UInt32 processed;
|
||||
if (!_outFile.Write(data, size, processed))
|
||||
return Get_HRESULT_LastError();
|
||||
_crc = CrcUpdate(_crc, data, processed);
|
||||
_size += processed;
|
||||
return (processed == size) ? S_OK : E_FAIL;
|
||||
|
||||
#else
|
||||
|
||||
const size_t newSize = _size + size;
|
||||
if (newSize < _size)
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_dynBuffer.EnsureCapacity(newSize))
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy(((Byte *)_dynBuffer) + _size, data, size);
|
||||
_size = newSize;
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
if (!_outFile.WriteFull(data, size))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
_crc = CrcUpdate(_crc, data, size);
|
||||
_size += size;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
UInt64 rem = _size;
|
||||
// if (rem == 0) return S_OK;
|
||||
|
||||
if (!_outFile.Close())
|
||||
return E_FAIL;
|
||||
const size_t numFilled = _numFilled;
|
||||
_numFilled = 0;
|
||||
|
||||
UInt64 size = 0;
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
|
||||
if (_bufPos != 0)
|
||||
for (size_t i = 0; i < numFilled; i++)
|
||||
{
|
||||
RINOK(WriteStream(stream, _buf, _bufPos));
|
||||
crc = CrcUpdate(crc, _buf, _bufPos);
|
||||
size += _bufPos;
|
||||
}
|
||||
|
||||
if (_tempFileCreated)
|
||||
{
|
||||
NIO::CInFile inFile;
|
||||
if (!inFile.Open(_tempFile.GetPath()))
|
||||
if (rem == 0)
|
||||
return E_FAIL;
|
||||
while (size < _size)
|
||||
size_t cur = kBufSize;
|
||||
if (cur > rem)
|
||||
cur = (size_t)rem;
|
||||
RINOK(WriteStream(stream, _bufs[i], cur))
|
||||
rem -= cur;
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
// we will use _bufs[0] later for writing from temp file
|
||||
if (i != 0 || !_tempFile_Created)
|
||||
#endif
|
||||
{
|
||||
UInt32 processed;
|
||||
if (!inFile.ReadPart(_buf, kTempBufSize, processed))
|
||||
return E_FAIL;
|
||||
if (processed == 0)
|
||||
break;
|
||||
RINOK(WriteStream(stream, _buf, processed));
|
||||
crc = CrcUpdate(crc, _buf, processed);
|
||||
size += processed;
|
||||
MyFree(_bufs[i]);
|
||||
_bufs[i] = NULL;
|
||||
}
|
||||
}
|
||||
return (_crc == crc && size == _size) ? S_OK : E_FAIL;
|
||||
|
||||
#else
|
||||
|
||||
return WriteStream(stream, (const Byte *)_dynBuffer, _size);
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
|
||||
#endif
|
||||
}
|
||||
if (rem == 0)
|
||||
return _tempFile_Created ? E_FAIL : S_OK;
|
||||
|
||||
/*
|
||||
STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
|
||||
{
|
||||
if (!_buf->Write(data, size))
|
||||
{
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
if (!_tempFile_Created)
|
||||
return E_FAIL;
|
||||
|
||||
if (!_outFile.Close())
|
||||
return GetLastError_noZero_HRESULT();
|
||||
|
||||
HRESULT hres;
|
||||
void *buf = GetBuf(0); // index
|
||||
if (!buf)
|
||||
hres = E_OUTOFMEMORY;
|
||||
else
|
||||
{
|
||||
NWindows::NFile::NIO::CInFile inFile;
|
||||
if (!inFile.Open(_tempFile.GetPath()))
|
||||
hres = GetLastError_noZero_HRESULT();
|
||||
else
|
||||
{
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
for (;;)
|
||||
{
|
||||
size_t processed;
|
||||
if (!inFile.ReadFull(buf, kBufSize, processed))
|
||||
{
|
||||
hres = GetLastError_noZero_HRESULT();
|
||||
break;
|
||||
}
|
||||
if (processed == 0)
|
||||
{
|
||||
// we compare crc without CRC_GET_DIGEST
|
||||
hres = (_crc == crc ? S_OK : E_FAIL);
|
||||
break;
|
||||
}
|
||||
size_t n = processed;
|
||||
if (n > rem)
|
||||
n = (size_t)rem;
|
||||
hres = WriteStream(stream, buf, n);
|
||||
if (hres != S_OK)
|
||||
break;
|
||||
crc = CrcUpdate(crc, buf, n);
|
||||
rem -= n;
|
||||
if (n != processed)
|
||||
{
|
||||
hres = E_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (processed)
|
||||
*processed = size;
|
||||
return S_OK;
|
||||
|
||||
// _tempFile.DisableDeleting(); // for debug
|
||||
_tempFile.Remove();
|
||||
RINOK(hres)
|
||||
|
||||
#endif
|
||||
|
||||
return rem == 0 ? S_OK : E_FAIL;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,66 +1,45 @@
|
||||
// InOutTempBuffer.h
|
||||
|
||||
#ifndef __IN_OUT_TEMP_BUFFER_H
|
||||
#define __IN_OUT_TEMP_BUFFER_H
|
||||
#ifndef ZIP7_INC_IN_OUT_TEMP_BUFFER_H
|
||||
#define ZIP7_INC_IN_OUT_TEMP_BUFFER_H
|
||||
|
||||
#ifdef _WIN32
|
||||
// #define USE_InOutTempBuffer_FILE
|
||||
#endif
|
||||
// #ifdef _WIN32
|
||||
#define USE_InOutTempBuffer_FILE
|
||||
// #endif
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
#include "../../Windows/FileDir.h"
|
||||
#else
|
||||
#include "StreamObjects.h"
|
||||
#endif
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CInOutTempBuffer
|
||||
{
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
UInt64 _size;
|
||||
void **_bufs;
|
||||
size_t _numBufs;
|
||||
size_t _numFilled;
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
|
||||
bool _tempFile_Created;
|
||||
bool _useMemOnly;
|
||||
UInt32 _crc;
|
||||
// COutFile object must be declared after CTempFile object for correct destructor order
|
||||
NWindows::NFile::NDir::CTempFile _tempFile;
|
||||
NWindows::NFile::NIO::COutFile _outFile;
|
||||
bool _tempFileCreated;
|
||||
Byte *_buf;
|
||||
size_t _bufPos;
|
||||
UInt64 _size;
|
||||
UInt32 _crc;
|
||||
|
||||
#else
|
||||
|
||||
CByteDynBuffer _dynBuffer;
|
||||
size_t _size;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CLASS_NO_COPY(CInOutTempBuffer);
|
||||
void *GetBuf(size_t index);
|
||||
|
||||
Z7_CLASS_NO_COPY(CInOutTempBuffer)
|
||||
public:
|
||||
CInOutTempBuffer();
|
||||
void Create();
|
||||
|
||||
#ifdef USE_InOutTempBuffer_FILE
|
||||
~CInOutTempBuffer();
|
||||
#endif
|
||||
|
||||
void InitWriting();
|
||||
HRESULT Write_HRESULT(const void *data, UInt32 size);
|
||||
HRESULT WriteToStream(ISequentialOutStream *stream);
|
||||
UInt64 GetDataSize() const { return _size; }
|
||||
};
|
||||
|
||||
/*
|
||||
class CSequentialOutTempBufferImp:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CInOutTempBuffer *_buf;
|
||||
public:
|
||||
void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "LimitedStreams.h"
|
||||
|
||||
STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
{
|
||||
@@ -27,7 +27,7 @@ STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *p
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -46,7 +46,7 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
RINOK(SeekToPhys())
|
||||
}
|
||||
HRESULT res = _stream->Read(data, size, &size);
|
||||
if (processedSize)
|
||||
@@ -56,7 +56,7 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -75,17 +75,17 @@ STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new
|
||||
|
||||
HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)
|
||||
{
|
||||
*resStream = 0;
|
||||
*resStream = NULL;
|
||||
CLimitedInStream *streamSpec = new CLimitedInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||
streamSpec->SetStream(inStream);
|
||||
RINOK(streamSpec->InitAndSeek(pos, size));
|
||||
RINOK(streamSpec->InitAndSeek(pos, size))
|
||||
streamSpec->SeekToStart();
|
||||
*resStream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -110,7 +110,7 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
RINOK(SeekToPhys())
|
||||
}
|
||||
|
||||
_curRem = blockSize - offsetInBlock;
|
||||
@@ -130,7 +130,7 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -150,7 +150,7 @@ STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -201,7 +201,7 @@ STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize
|
||||
if (_phyPos != phy)
|
||||
{
|
||||
_phyPos = (UInt64)0 - 1; // we don't trust seek_pos in case of error
|
||||
RINOK(Stream->Seek((Int64)phy, STREAM_SEEK_SET, NULL));
|
||||
RINOK(InStream_SeekSet(Stream, phy))
|
||||
_phyPos = phy;
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,7 @@ STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -236,7 +236,7 @@ STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (processedSize)
|
||||
@@ -263,7 +263,7 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 cur;
|
||||
HRESULT res = Stream->Read(data, size, &cur);
|
||||
@@ -273,7 +273,7 @@ STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -282,7 +282,7 @@ STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
|
||||
case STREAM_SEEK_END:
|
||||
{
|
||||
UInt64 pos = 0;
|
||||
RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos));
|
||||
RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos))
|
||||
if (pos < Offset)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = pos - Offset;
|
||||
@@ -297,10 +297,10 @@ STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
|
||||
_virtPos = (UInt64)offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL);
|
||||
return InStream_SeekSet(Stream, Offset + _virtPos);
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -329,7 +329,7 @@ STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *proce
|
||||
if (newPos != _physPos)
|
||||
{
|
||||
_physPos = newPos;
|
||||
RINOK(SeekToPhys());
|
||||
RINOK(SeekToPhys())
|
||||
}
|
||||
res = _stream->Read(data, size, &size);
|
||||
_physPos += size;
|
||||
@@ -340,7 +340,7 @@ STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *proce
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -357,7 +357,7 @@ STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt6
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 cur;
|
||||
HRESULT res = Stream->Write(data, size, &cur);
|
||||
@@ -369,7 +369,7 @@ STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *proces
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -386,7 +386,7 @@ STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
|
||||
return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize)
|
||||
Z7_COM7F_IMF(CTailOutStream::SetSize(UInt64 newSize))
|
||||
{
|
||||
_virtSize = newSize;
|
||||
return Stream->SetSize(Offset + newSize);
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
// LimitedStreams.h
|
||||
|
||||
#ifndef __LIMITED_STREAMS_H
|
||||
#define __LIMITED_STREAMS_H
|
||||
#ifndef ZIP7_INC_LIMITED_STREAMS_H
|
||||
#define ZIP7_INC_LIMITED_STREAMS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
class CLimitedSequentialInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
#include "StreamUtils.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CLimitedSequentialInStream
|
||||
, ISequentialInStream
|
||||
)
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt64 _pos;
|
||||
@@ -25,26 +27,22 @@ public:
|
||||
_pos = 0;
|
||||
_wasFinished = false;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
UInt64 GetSize() const { return _pos; }
|
||||
UInt64 GetRem() const { return _size - _pos; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
class CLimitedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CLimitedInStream
|
||||
)
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt64 _size;
|
||||
UInt64 _startOffset;
|
||||
|
||||
HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); }
|
||||
HRESULT SeekToPhys() { return InStream_SeekSet(_stream, _physPos); }
|
||||
public:
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
|
||||
@@ -55,21 +53,15 @@ public:
|
||||
_size = size;
|
||||
return SeekToPhys();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);
|
||||
|
||||
class CClusterInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CClusterInStream
|
||||
)
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
UInt32 _curRem;
|
||||
@@ -80,7 +72,7 @@ public:
|
||||
CRecordVector<UInt32> Vector;
|
||||
UInt64 StartOffset;
|
||||
|
||||
HRESULT SeekToPhys() { return Stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); }
|
||||
HRESULT SeekToPhys() { return InStream_SeekSet(Stream, _physPos); }
|
||||
|
||||
HRESULT InitAndSeek()
|
||||
{
|
||||
@@ -94,11 +86,6 @@ public:
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
|
||||
@@ -114,23 +101,18 @@ struct CSeekExtent
|
||||
bool Is_ZeroFill() const { return Phy == k_SeekExtent_Phy_Type_ZeroFill; }
|
||||
};
|
||||
|
||||
class CExtentsStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CExtentsStream
|
||||
)
|
||||
UInt64 _virtPos;
|
||||
UInt64 _phyPos;
|
||||
unsigned _prevExtentIndex;
|
||||
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CRecordVector<CSeekExtent> Extents;
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
void ReleaseStream() { Stream.Release(); }
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
@@ -141,17 +123,15 @@ public:
|
||||
|
||||
|
||||
|
||||
class CLimitedSequentialOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CLimitedSequentialOutStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
bool _overflow;
|
||||
bool _overflowIsAllowed;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(UInt64 size, bool overflowIsAllowed = false)
|
||||
@@ -165,10 +145,9 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class CTailInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CTailInStream
|
||||
)
|
||||
UInt64 _virtPos;
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
@@ -178,19 +157,13 @@ public:
|
||||
{
|
||||
_virtPos = 0;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Stream->Seek((Int64)Offset, STREAM_SEEK_SET, NULL); }
|
||||
HRESULT SeekToStart() { return InStream_SeekSet(Stream, Offset); }
|
||||
};
|
||||
|
||||
class CLimitedCachedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CLimitedCachedInStream
|
||||
)
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _physPos;
|
||||
@@ -201,8 +174,7 @@ class CLimitedCachedInStream:
|
||||
size_t _cacheSize;
|
||||
size_t _cachePhyPos;
|
||||
|
||||
|
||||
HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); }
|
||||
HRESULT SeekToPhys() { return InStream_SeekSet(_stream, _physPos); }
|
||||
public:
|
||||
CByteBuffer Buffer;
|
||||
|
||||
@@ -223,37 +195,27 @@ public:
|
||||
return SeekToPhys();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
|
||||
};
|
||||
|
||||
class CTailOutStream:
|
||||
|
||||
class CTailOutStream Z7_final :
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_IFACES_IMP_UNK_2(ISequentialOutStream, IOutStream)
|
||||
|
||||
UInt64 _virtPos;
|
||||
UInt64 _virtSize;
|
||||
public:
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
UInt64 Offset;
|
||||
|
||||
virtual ~CTailOutStream() {}
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
|
||||
|
||||
void Init()
|
||||
{
|
||||
_virtPos = 0;
|
||||
_virtSize = 0;
|
||||
}
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// LockedStream.h
|
||||
|
||||
#ifndef __LOCKED_STREAM_H
|
||||
#define __LOCKED_STREAM_H
|
||||
#ifndef ZIP7_INC_LOCKED_STREAM_H
|
||||
#define ZIP7_INC_LOCKED_STREAM_H
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,8 +34,8 @@ bool CMemBlockManager::AllocateSpace_bool(size_t numBlocks)
|
||||
void CMemBlockManager::FreeSpace()
|
||||
{
|
||||
::MidFree(_data);
|
||||
_data = 0;
|
||||
_headFree= 0;
|
||||
_data = NULL;
|
||||
_headFree= NULL;
|
||||
}
|
||||
|
||||
void *CMemBlockManager::AllocateBlock()
|
||||
@@ -157,7 +157,7 @@ HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStr
|
||||
curSize = (size_t)totalSize;
|
||||
if (blockIndex >= Blocks.Size())
|
||||
return E_FAIL;
|
||||
RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));
|
||||
RINOK(WriteStream(outStream, Blocks[blockIndex], curSize))
|
||||
totalSize -= curSize;
|
||||
}
|
||||
return S_OK;
|
||||
@@ -207,7 +207,7 @@ void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManag
|
||||
blocks.Blocks.Add(Blocks[i]);
|
||||
else
|
||||
FreeBlock(i, memManager);
|
||||
Blocks[i] = 0;
|
||||
Blocks[i] = NULL;
|
||||
totalSize += blockSize;
|
||||
}
|
||||
blocks.TotalSize = TotalSize;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// MemBlocks.h
|
||||
|
||||
#ifndef __MEM_BLOCKS_H
|
||||
#define __MEM_BLOCKS_H
|
||||
#ifndef ZIP7_INC_MEM_BLOCKS_H
|
||||
#define ZIP7_INC_MEM_BLOCKS_H
|
||||
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
@@ -30,7 +30,7 @@ class CMemBlockManagerMt: public CMemBlockManager
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSection _criticalSection;
|
||||
public:
|
||||
SYNC_OBJ_DECL(Synchro);
|
||||
SYNC_OBJ_DECL(Synchro)
|
||||
NWindows::NSynchronization::CSemaphore_WFMO Semaphore;
|
||||
|
||||
CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}
|
||||
@@ -62,7 +62,7 @@ struct CMemLockBlocks: public CMemBlocks
|
||||
{
|
||||
bool LockMode;
|
||||
|
||||
CMemLockBlocks(): LockMode(true) {};
|
||||
CMemLockBlocks(): LockMode(true) {}
|
||||
void Free(CMemBlockManagerMt *memManager);
|
||||
void FreeBlock(unsigned index, CMemBlockManagerMt *memManager);
|
||||
// HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// MethodId.h
|
||||
|
||||
#ifndef __7Z_METHOD_ID_H
|
||||
#define __7Z_METHOD_ID_H
|
||||
#ifndef ZIP7_INC_7Z_METHOD_ID_H
|
||||
#define ZIP7_INC_7Z_METHOD_ID_H
|
||||
|
||||
#include "../../Common/MyTypes.h"
|
||||
|
||||
|
||||
@@ -379,14 +379,14 @@ struct CNameToPropID
|
||||
|
||||
|
||||
// the following are related to NCoderPropID::EEnum values
|
||||
|
||||
// NCoderPropID::k_NUM_DEFINED
|
||||
static const CNameToPropID g_NameToPropID[] =
|
||||
{
|
||||
{ VT_UI4, "" },
|
||||
{ VT_UI4, "d" },
|
||||
{ VT_UI4, "mem" },
|
||||
{ VT_UI4, "o" },
|
||||
{ VT_UI4, "c" },
|
||||
{ VT_UI8, "c" },
|
||||
{ VT_UI4, "pb" },
|
||||
{ VT_UI4, "lc" },
|
||||
{ VT_UI4, "lp" },
|
||||
@@ -400,15 +400,57 @@ static const CNameToPropID g_NameToPropID[] =
|
||||
{ VT_UI4, "x" },
|
||||
{ VT_UI8, "reduce" },
|
||||
{ VT_UI8, "expect" },
|
||||
{ VT_UI4, "b" },
|
||||
{ VT_UI8, "cc" }, // "cc" in v23, "b" in v22.01
|
||||
{ VT_UI4, "check" },
|
||||
{ VT_BSTR, "filter" },
|
||||
{ VT_UI8, "memuse" }
|
||||
{ VT_UI8, "memuse" },
|
||||
{ VT_UI8, "aff" },
|
||||
{ VT_UI4, "offset" },
|
||||
{ VT_UI4, "zhb" }
|
||||
/*
|
||||
,
|
||||
// { VT_UI4, "zhc" },
|
||||
// { VT_UI4, "zhd" },
|
||||
// { VT_UI4, "zcb" },
|
||||
{ VT_UI4, "dc" },
|
||||
{ VT_UI4, "zx" },
|
||||
{ VT_UI4, "zf" },
|
||||
{ VT_UI4, "zmml" },
|
||||
{ VT_UI4, "zov" },
|
||||
{ VT_BOOL, "zmfr" },
|
||||
{ VT_BOOL, "zle" }, // long enable
|
||||
// { VT_UI4, "zldb" },
|
||||
{ VT_UI4, "zld" },
|
||||
{ VT_UI4, "zlhb" },
|
||||
{ VT_UI4, "zlmml" },
|
||||
{ VT_UI4, "zlbb" },
|
||||
{ VT_UI4, "zlhrb" },
|
||||
{ VT_BOOL, "zwus" },
|
||||
{ VT_BOOL, "zshp" },
|
||||
{ VT_BOOL, "zshs" },
|
||||
{ VT_BOOL, "zshe" },
|
||||
{ VT_BOOL, "zshg" },
|
||||
{ VT_UI4, "zpsm" }
|
||||
*/
|
||||
// { VT_UI4, "mcb" }, // mc log version
|
||||
// { VT_UI4, "ztlen" }, // fb ?
|
||||
};
|
||||
|
||||
/*
|
||||
#if defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 200410L) || (defined(_MSC_VER) && _MSC_VER >= 1600)
|
||||
|
||||
#if (defined(__cplusplus) && __cplusplus < 201103L) \
|
||||
&& defined(__clang__) && __clang_major__ >= 4
|
||||
#pragma GCC diagnostic ignored "-Wc11-extensions"
|
||||
#endif
|
||||
static_assert(Z7_ARRAY_SIZE(g_NameToPropID) == NCoderPropID::k_NUM_DEFINED,
|
||||
"g_NameToPropID doesn't match NCoderPropID enum");
|
||||
#endif
|
||||
*/
|
||||
|
||||
static int FindPropIdExact(const UString &name)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++)
|
||||
for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NameToPropID); i++)
|
||||
if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))
|
||||
return (int)i;
|
||||
return -1;
|
||||
@@ -493,6 +535,10 @@ static bool IsLogSizeProp(PROPID propid)
|
||||
case NCoderPropID::kUsedMemorySize:
|
||||
case NCoderPropID::kBlockSize:
|
||||
case NCoderPropID::kBlockSize2:
|
||||
/*
|
||||
case NCoderPropID::kChainSize:
|
||||
case NCoderPropID::kLdmWindowSize:
|
||||
*/
|
||||
// case NCoderPropID::kReduceSize:
|
||||
return true;
|
||||
}
|
||||
@@ -503,14 +549,19 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
|
||||
{
|
||||
int index = FindPropIdExact(name);
|
||||
if (index < 0)
|
||||
return E_INVALIDARG;
|
||||
{
|
||||
// 'b' was used as NCoderPropID::kBlockSize2 before v23
|
||||
if (!name.IsEqualTo_Ascii_NoCase("b") || value.Find(L':') >= 0)
|
||||
return E_INVALIDARG;
|
||||
index = NCoderPropID::kBlockSize2;
|
||||
}
|
||||
const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
|
||||
CProp prop;
|
||||
prop.Id = (unsigned)index;
|
||||
|
||||
if (IsLogSizeProp(prop.Id))
|
||||
{
|
||||
RINOK(StringToDictSize(value, prop.Value));
|
||||
RINOK(StringToDictSize(value, prop.Value))
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -561,7 +612,7 @@ HRESULT CMethodProps::ParseParamsFromString(const UString &srcString)
|
||||
const UString ¶m = params[i];
|
||||
UString name, value;
|
||||
SplitParam(param, name, value);
|
||||
RINOK(SetParam(name, value));
|
||||
RINOK(SetParam(name, value))
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -582,7 +633,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
|
||||
}
|
||||
|
||||
// {realName}=value
|
||||
int index = FindPropIdExact(realName);
|
||||
const int index = FindPropIdExact(realName);
|
||||
if (index < 0)
|
||||
return E_INVALIDARG;
|
||||
const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
|
||||
@@ -591,7 +642,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
|
||||
|
||||
if (IsLogSizeProp(prop.Id))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_DictSize(value, prop.Value));
|
||||
RINOK(PROPVARIANT_to_DictSize(value, prop.Value))
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// MethodProps.h
|
||||
|
||||
#ifndef __7Z_METHOD_PROPS_H
|
||||
#define __7Z_METHOD_PROPS_H
|
||||
#ifndef ZIP7_INC_7Z_METHOD_PROPS_H
|
||||
#define ZIP7_INC_7Z_METHOD_PROPS_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
849
CPP/7zip/Common/MultiOutStream.cpp
Executable file
849
CPP/7zip/Common/MultiOutStream.cpp
Executable file
@@ -0,0 +1,849 @@
|
||||
// MultiOutStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #define DEBUG_VOLUMES
|
||||
|
||||
#ifdef DEBUG_VOLUMES
|
||||
#include <stdio.h>
|
||||
#define PRF(x) x;
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../../Windows/FileDir.h"
|
||||
#include "../../Windows/FileFind.h"
|
||||
#include "../../Windows/System.h"
|
||||
|
||||
#include "MultiOutStream.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
static const unsigned k_NumVols_MAX = k_VectorSizeMax - 1;
|
||||
// 2; // for debug
|
||||
|
||||
/*
|
||||
#define UPDATE_HRES(hres, x) \
|
||||
{ const HRESULT res2 = (x); if (hres == SZ_OK) hres = res2; }
|
||||
*/
|
||||
|
||||
HRESULT CMultiOutStream::Destruct()
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
HRESULT hres = S_OK;
|
||||
HRESULT hres3 = S_OK;
|
||||
|
||||
while (!Streams.IsEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
HRESULT hres2;
|
||||
if (NeedDelete)
|
||||
{
|
||||
/* we could call OptReOpen_and_SetSize() to test that we try to delete correct file,
|
||||
but we cannot guarantee that (RealSize) will be correct after Write() or another failures.
|
||||
And we still want to delete files even for such cases.
|
||||
So we don't check for OptReOpen_and_SetSize() here: */
|
||||
// if (OptReOpen_and_SetSize(Streams.Size() - 1, 0) == S_OK)
|
||||
hres2 = CloseStream_and_DeleteFile(Streams.Size() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hres2 = CloseStream(Streams.Size() - 1);
|
||||
}
|
||||
if (hres == S_OK)
|
||||
hres = hres2;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
hres3 = E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
{
|
||||
/* Stream was released in CloseStream_*() above already, and it was removed from linked list
|
||||
it's some unexpected case, if Stream is still attached here.
|
||||
So the following code is optional: */
|
||||
CVolStream &s = Streams.Back();
|
||||
if (s.Stream)
|
||||
{
|
||||
if (hres3 == S_OK)
|
||||
hres3 = E_FAIL;
|
||||
s.Stream.Detach();
|
||||
/* it will be not failure, even if we call RemoveFromLinkedList()
|
||||
twice for same CVolStream in this Destruct() function */
|
||||
RemoveFromLinkedList(Streams.Size() - 1);
|
||||
}
|
||||
}
|
||||
Streams.DeleteBack();
|
||||
// Delete_LastStream_Records();
|
||||
}
|
||||
|
||||
if (hres == S_OK)
|
||||
hres = hres3;
|
||||
if (hres == S_OK && NumListItems != 0)
|
||||
hres = E_FAIL;
|
||||
return hres;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
CMultiOutStream::~CMultiOutStream()
|
||||
{
|
||||
// we try to avoid exception in destructors
|
||||
Destruct();
|
||||
}
|
||||
|
||||
|
||||
void CMultiOutStream::Init(const CRecordVector<UInt64> &sizes)
|
||||
{
|
||||
Streams.Clear();
|
||||
InitLinkedList();
|
||||
Sizes = sizes;
|
||||
NeedDelete = true;
|
||||
MTime_Defined = false;
|
||||
FinalVol_WasReopen = false;
|
||||
NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks();
|
||||
|
||||
_streamIndex = 0;
|
||||
_offsetPos = 0;
|
||||
_absPos = 0;
|
||||
_length = 0;
|
||||
_absLimit = (UInt64)(Int64)-1;
|
||||
|
||||
_restrict_Begin = 0;
|
||||
_restrict_End = (UInt64)(Int64)-1;
|
||||
_restrict_Global = 0;
|
||||
|
||||
UInt64 sum = 0;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < Sizes.Size(); i++)
|
||||
{
|
||||
if (i >= k_NumVols_MAX)
|
||||
{
|
||||
_absLimit = sum;
|
||||
break;
|
||||
}
|
||||
const UInt64 size = Sizes[i];
|
||||
const UInt64 next = sum + size;
|
||||
if (next < sum)
|
||||
break;
|
||||
sum = next;
|
||||
}
|
||||
|
||||
// if (Sizes.IsEmpty()) throw "no volume sizes";
|
||||
const UInt64 size = Sizes.Back();
|
||||
if (size == 0)
|
||||
throw "zero size last volume";
|
||||
|
||||
if (i == Sizes.Size())
|
||||
if ((_absLimit - sum) / size >= (k_NumVols_MAX - i))
|
||||
_absLimit = sum + (k_NumVols_MAX - i) * size;
|
||||
}
|
||||
|
||||
|
||||
/* IsRestricted():
|
||||
we must call only if volume is full (s.RealSize==VolSize) or finished.
|
||||
the function doesn't use VolSize and it uses s.RealSize instead.
|
||||
it returns true : if stream is restricted, and we can't close that stream
|
||||
it returns false : if there is no restriction, and we can close that stream
|
||||
Note: (RealSize == 0) (empty volume) on restriction bounds are supposed as non-restricted
|
||||
*/
|
||||
bool CMultiOutStream::IsRestricted(const CVolStream &s) const
|
||||
{
|
||||
if (s.Start < _restrict_Global)
|
||||
return true;
|
||||
if (_restrict_Begin == _restrict_End)
|
||||
return false;
|
||||
if (_restrict_Begin <= s.Start)
|
||||
return _restrict_End > s.Start;
|
||||
return _restrict_Begin < s.Start + s.RealSize;
|
||||
}
|
||||
|
||||
/*
|
||||
// this function check also _length and volSize
|
||||
bool CMultiOutStream::IsRestricted_for_Close(unsigned index) const
|
||||
{
|
||||
const CVolStream &s = Streams[index];
|
||||
if (_length <= s.Start) // we don't close streams after the end, because we still can write them later
|
||||
return true;
|
||||
// (_length > s.Start)
|
||||
const UInt64 volSize = GetVolSize_for_Stream(index);
|
||||
if (volSize == 0)
|
||||
return IsRestricted_Empty(s);
|
||||
if (_length - s.Start < volSize)
|
||||
return true;
|
||||
return IsRestricted(s);
|
||||
}
|
||||
*/
|
||||
|
||||
FString CMultiOutStream::GetFilePath(unsigned index)
|
||||
{
|
||||
FString name;
|
||||
name.Add_UInt32(index + 1);
|
||||
while (name.Len() < 3)
|
||||
name.InsertAtFront(FTEXT('0'));
|
||||
name.Insert(0, Prefix);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
// we close stream, but we still keep item in Streams[] vector
|
||||
HRESULT CMultiOutStream::CloseStream(unsigned index)
|
||||
{
|
||||
CVolStream &s = Streams[index];
|
||||
if (s.Stream)
|
||||
{
|
||||
RINOK(s.StreamSpec->Close())
|
||||
// the following two commands must be called together:
|
||||
s.Stream.Release();
|
||||
RemoveFromLinkedList(index);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
// we close stream and delete file, but we still keep item in Streams[] vector
|
||||
HRESULT CMultiOutStream::CloseStream_and_DeleteFile(unsigned index)
|
||||
{
|
||||
PRF(printf("\n====== %u, CloseStream_AndDelete \n", index));
|
||||
RINOK(CloseStream(index))
|
||||
FString path = GetFilePath(index);
|
||||
path += Streams[index].Postfix;
|
||||
// we can checki that file exist
|
||||
// if (NFind::DoesFileExist_Raw(path))
|
||||
if (!DeleteFileAlways(path))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiOutStream::CloseStream_and_FinalRename(unsigned index)
|
||||
{
|
||||
PRF(printf("\n====== %u, CloseStream_and_FinalRename \n", index));
|
||||
CVolStream &s = Streams[index];
|
||||
// HRESULT res = S_OK;
|
||||
bool mtime_WasSet = false;
|
||||
if (MTime_Defined && s.Stream)
|
||||
{
|
||||
if (s.StreamSpec->SetMTime(&MTime))
|
||||
mtime_WasSet = true;
|
||||
// else res = GetLastError_noZero_HRESULT();
|
||||
}
|
||||
|
||||
RINOK(CloseStream(index))
|
||||
if (s.Postfix.IsEmpty()) // if Postfix is empty, the path is already final
|
||||
return S_OK;
|
||||
const FString path = GetFilePath(index);
|
||||
FString tempPath = path;
|
||||
tempPath += s.Postfix;
|
||||
|
||||
if (MTime_Defined && !mtime_WasSet)
|
||||
{
|
||||
if (!SetDirTime(tempPath, NULL, NULL, &MTime))
|
||||
{
|
||||
// res = GetLastError_noZero_HRESULT();
|
||||
}
|
||||
}
|
||||
if (!MyMoveFile(tempPath, path))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
/* we clear CVolStream::Postfix. So we will not use Temp path
|
||||
anymore for this stream, and we will work only with final path */
|
||||
s.Postfix.Empty();
|
||||
// we can ignore set_mtime error or we can return it
|
||||
return S_OK;
|
||||
// return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiOutStream::PrepareToOpenNew()
|
||||
{
|
||||
if (NumListItems < NumOpenFiles_AllowedMax)
|
||||
return S_OK;
|
||||
/* when we create zip archive: in most cases we need only starting
|
||||
data of restricted region for rewriting zip's local header.
|
||||
So here we close latest created volume (from Head), and we try to
|
||||
keep oldest volumes that will be used for header rewriting later. */
|
||||
const int index = Head;
|
||||
if (index == -1)
|
||||
return E_FAIL;
|
||||
PRF(printf("\n== %u, PrepareToOpenNew::CloseStream, NumListItems =%u \n", index, NumListItems));
|
||||
/* we don't expect non-restricted stream here in normal cases (if _restrict_Global was not changed).
|
||||
if there was non-restricted stream, it should be closed before */
|
||||
// if (!IsRestricted_for_Close(index)) return CloseStream_and_FinalRename(index);
|
||||
return CloseStream((unsigned)index);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiOutStream::CreateNewStream(UInt64 newSize)
|
||||
{
|
||||
PRF(printf("\n== %u, CreateNewStream, size =%u \n", Streams.Size(), (unsigned)newSize));
|
||||
|
||||
if (Streams.Size() >= k_NumVols_MAX)
|
||||
return E_INVALIDARG; // E_OUTOFMEMORY
|
||||
|
||||
RINOK(PrepareToOpenNew())
|
||||
CVolStream s;
|
||||
s.StreamSpec = new COutFileStream;
|
||||
s.Stream = s.StreamSpec;
|
||||
const FString path = GetFilePath(Streams.Size());
|
||||
|
||||
if (NFind::DoesFileExist_Raw(path))
|
||||
return HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
||||
if (!CreateTempFile2(path, false, s.Postfix, &s.StreamSpec->File))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
|
||||
s.Start = GetGlobalOffset_for_NewStream();
|
||||
s.Pos = 0;
|
||||
s.RealSize = 0;
|
||||
|
||||
const unsigned index = Streams.Add(s);
|
||||
InsertToLinkedList(index);
|
||||
|
||||
if (newSize != 0)
|
||||
return s.SetSize2(newSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiOutStream::CreateStreams_If_Required(unsigned streamIndex)
|
||||
{
|
||||
// UInt64 lastStreamSize = 0;
|
||||
for (;;)
|
||||
{
|
||||
const unsigned numStreamsBefore = Streams.Size();
|
||||
if (streamIndex < numStreamsBefore)
|
||||
return S_OK;
|
||||
UInt64 newSize;
|
||||
if (streamIndex == numStreamsBefore)
|
||||
{
|
||||
// it's final volume that will be used for real writing.
|
||||
/* SetSize(_offsetPos) is not required,
|
||||
because the file Size will be set later by calling Seek() with Write() */
|
||||
newSize = 0; // lastStreamSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's intermediate volume. So we need full volume size
|
||||
newSize = GetVolSize_for_Stream(numStreamsBefore);
|
||||
}
|
||||
|
||||
RINOK(CreateNewStream(newSize))
|
||||
|
||||
// optional check
|
||||
if (numStreamsBefore + 1 != Streams.Size()) return E_FAIL;
|
||||
|
||||
if (streamIndex != numStreamsBefore)
|
||||
{
|
||||
// it's intermediate volume. So we can close it, if it's non-restricted
|
||||
bool isRestricted;
|
||||
{
|
||||
const CVolStream &s = Streams[numStreamsBefore];
|
||||
if (newSize == 0)
|
||||
isRestricted = IsRestricted_Empty(s);
|
||||
else
|
||||
isRestricted = IsRestricted(s);
|
||||
}
|
||||
if (!isRestricted)
|
||||
{
|
||||
RINOK(CloseStream_and_FinalRename(numStreamsBefore))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiOutStream::ReOpenStream(unsigned streamIndex)
|
||||
{
|
||||
PRF(printf("\n====== %u, ReOpenStream \n", streamIndex));
|
||||
RINOK(PrepareToOpenNew())
|
||||
CVolStream &s = Streams[streamIndex];
|
||||
|
||||
FString path = GetFilePath(streamIndex);
|
||||
path += s.Postfix;
|
||||
|
||||
s.StreamSpec = new COutFileStream;
|
||||
s.Stream = s.StreamSpec;
|
||||
s.Pos = 0;
|
||||
|
||||
HRESULT hres;
|
||||
if (s.StreamSpec->Open(path, OPEN_EXISTING))
|
||||
{
|
||||
if (s.Postfix.IsEmpty())
|
||||
{
|
||||
/* it's unexpected case that we open finished volume.
|
||||
It can mean that the code for restriction is incorrect */
|
||||
FinalVol_WasReopen = true;
|
||||
}
|
||||
UInt64 realSize = 0;
|
||||
hres = s.StreamSpec->GetSize(&realSize);
|
||||
if (hres == S_OK)
|
||||
{
|
||||
if (realSize == s.RealSize)
|
||||
{
|
||||
InsertToLinkedList(streamIndex);
|
||||
return S_OK;
|
||||
}
|
||||
// file size was changed between Close() and ReOpen()
|
||||
// we must release Stream to be consistent with linked list
|
||||
hres = E_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
hres = GetLastError_noZero_HRESULT();
|
||||
s.Stream.Release();
|
||||
s.StreamSpec = NULL;
|
||||
return hres;
|
||||
}
|
||||
|
||||
|
||||
/* Sets size of stream, if new size is not equal to old size (RealSize).
|
||||
If stream was closed and size change is required, it reopens the stream. */
|
||||
|
||||
HRESULT CMultiOutStream::OptReOpen_and_SetSize(unsigned index, UInt64 size)
|
||||
{
|
||||
CVolStream &s = Streams[index];
|
||||
if (size == s.RealSize)
|
||||
return S_OK;
|
||||
if (!s.Stream)
|
||||
{
|
||||
RINOK(ReOpenStream(index))
|
||||
}
|
||||
PRF(printf("\n== %u, OptReOpen_and_SetSize, size =%u RealSize = %u\n", index, (unsigned)size, (unsigned)s.RealSize));
|
||||
// comment it to debug tail after data
|
||||
return s.SetSize2(size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
call Normalize_finalMode(false), if _length was changed.
|
||||
for all streams starting after _length:
|
||||
- it sets zero size
|
||||
- it still keeps file open
|
||||
Note: after _length reducing with CMultiOutStream::SetSize() we can
|
||||
have very big number of empty streams at the end of Streams[] list.
|
||||
And Normalize_finalMode() will runs all these empty streams of Streams[] vector.
|
||||
So it can be ineffective, if we call Normalize_finalMode() many
|
||||
times after big reducing of (_length).
|
||||
|
||||
call Normalize_finalMode(true) to set final presentations of all streams
|
||||
for all streams starting after _length:
|
||||
- it sets zero size
|
||||
- it removes file
|
||||
- it removes CVolStream object from Streams[] vector
|
||||
|
||||
Note: we don't remove zero sized first volume, if (_length == 0)
|
||||
*/
|
||||
|
||||
HRESULT CMultiOutStream::Normalize_finalMode(bool finalMode)
|
||||
{
|
||||
PRF(printf("\n== Normalize_finalMode: _length =%d \n", (unsigned)_length));
|
||||
|
||||
unsigned i = Streams.Size();
|
||||
|
||||
UInt64 offset = 0;
|
||||
|
||||
/* At first we normalize (reduce or increase) the sizes of all existing
|
||||
streams in Streams[] that can be affected by changed _length.
|
||||
And we remove tailing zero-size streams, if (finalMode == true) */
|
||||
while (i != 0)
|
||||
{
|
||||
offset = Streams[--i].Start; // it's last item in Streams[]
|
||||
// we don't want to remove first volume
|
||||
if (offset < _length || i == 0)
|
||||
{
|
||||
const UInt64 volSize = GetVolSize_for_Stream(i);
|
||||
UInt64 size = _length - offset; // (size != 0) here
|
||||
if (size > volSize)
|
||||
size = volSize;
|
||||
RINOK(OptReOpen_and_SetSize(i, size))
|
||||
if (_length - offset <= volSize)
|
||||
return S_OK;
|
||||
// _length - offset > volSize
|
||||
offset += volSize;
|
||||
// _length > offset
|
||||
break;
|
||||
// UPDATE_HRES(res, OptReOpen_and_SetSize(i, size));
|
||||
}
|
||||
|
||||
/* we Set Size of stream to zero even for (finalMode==true), although
|
||||
that stream will be deleted in next commands */
|
||||
// UPDATE_HRES(res, OptReOpen_and_SetSize(i, 0));
|
||||
RINOK(OptReOpen_and_SetSize(i, 0))
|
||||
if (finalMode)
|
||||
{
|
||||
RINOK(CloseStream_and_DeleteFile(i))
|
||||
/* CVolStream::Stream was released above already, and it was
|
||||
removed from linked list. So we don't need to update linked list
|
||||
structure, when we delete last item in Streams[] */
|
||||
Streams.DeleteBack();
|
||||
// Delete_LastStream_Records();
|
||||
}
|
||||
}
|
||||
|
||||
/* now we create new zero-filled streams to cover all data up to _length */
|
||||
|
||||
if (_length == 0)
|
||||
return S_OK;
|
||||
|
||||
// (offset) is start offset of next stream after existing Streams[]
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// _length > offset
|
||||
const UInt64 volSize = GetVolSize_for_Stream(Streams.Size());
|
||||
UInt64 size = _length - offset; // (size != 0) here
|
||||
if (size > volSize)
|
||||
size = volSize;
|
||||
RINOK(CreateNewStream(size))
|
||||
if (_length - offset <= volSize)
|
||||
return S_OK;
|
||||
// _length - offset > volSize)
|
||||
offset += volSize;
|
||||
// _length > offset
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiOutStream::FinalFlush_and_CloseFiles(unsigned &numTotalVolumesRes)
|
||||
{
|
||||
// at first we remove unused zero-sized streams after _length
|
||||
HRESULT res = Normalize_finalMode(true);
|
||||
numTotalVolumesRes = Streams.Size();
|
||||
FOR_VECTOR (i, Streams)
|
||||
{
|
||||
const HRESULT res2 = CloseStream_and_FinalRename(i);
|
||||
if (res == S_OK)
|
||||
res = res2;
|
||||
}
|
||||
if (NumListItems != 0 && res == S_OK)
|
||||
res = E_FAIL;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool CMultiOutStream::SetMTime_Final(const CFiTime &mTime)
|
||||
{
|
||||
// we will set mtime only if new value differs from previous
|
||||
if (!FinalVol_WasReopen && MTime_Defined && Compare_FiTime(&MTime, &mTime) == 0)
|
||||
return true;
|
||||
bool res = true;
|
||||
FOR_VECTOR (i, Streams)
|
||||
{
|
||||
CVolStream &s = Streams[i];
|
||||
if (s.Stream)
|
||||
{
|
||||
if (!s.StreamSpec->SetMTime(&mTime))
|
||||
res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!SetDirTime(GetFilePath(i), NULL, NULL, &mTime))
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CMultiOutStream::SetSize(UInt64 newSize))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if ((Int64)newSize < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
if (newSize > _absLimit)
|
||||
{
|
||||
/* big seek value was sent to SetSize() or to Seek()+Write().
|
||||
It can mean one of two situations:
|
||||
1) some incorrect code called it with big seek value.
|
||||
2) volume size was small, and we have too big number of volumes
|
||||
*/
|
||||
/* in Windows SetEndOfFile() can return:
|
||||
ERROR_NEGATIVE_SEEK: for >= (1 << 63)
|
||||
ERROR_INVALID_PARAMETER: for > (16 TiB - 64 KiB)
|
||||
ERROR_DISK_FULL: for <= (16 TiB - 64 KiB)
|
||||
*/
|
||||
// return E_FAIL;
|
||||
// return E_OUTOFMEMORY;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (newSize > _length)
|
||||
{
|
||||
// we don't expect such case. So we just define global restriction */
|
||||
_restrict_Global = newSize;
|
||||
}
|
||||
else if (newSize < _restrict_Global)
|
||||
_restrict_Global = newSize;
|
||||
|
||||
PRF(printf("\n== SetSize, size =%u \n", (unsigned)newSize));
|
||||
|
||||
_length = newSize;
|
||||
return Normalize_finalMode(false);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CMultiOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (_absPos > _length)
|
||||
{
|
||||
// it create data only up to _absPos.
|
||||
// but we still can need additional new streams, if _absPos at range of volume
|
||||
RINOK(SetSize(_absPos))
|
||||
}
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
UInt64 volSize;
|
||||
{
|
||||
if (_streamIndex < Sizes.Size() - 1)
|
||||
{
|
||||
volSize = Sizes[_streamIndex];
|
||||
if (_offsetPos >= volSize)
|
||||
{
|
||||
_offsetPos -= volSize;
|
||||
_streamIndex++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
volSize = Sizes[Sizes.Size() - 1];
|
||||
if (_offsetPos >= volSize)
|
||||
{
|
||||
const UInt64 v = _offsetPos / volSize;
|
||||
if (v >= ((UInt32)(Int32)-1) - _streamIndex)
|
||||
return E_INVALIDARG;
|
||||
// throw 202208;
|
||||
_streamIndex += (unsigned)v;
|
||||
_offsetPos -= (unsigned)v * volSize;
|
||||
}
|
||||
if (_streamIndex >= k_NumVols_MAX)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
// (_offsetPos < volSize) here
|
||||
|
||||
/* we can need to create one or more streams here,
|
||||
vol_size for some streams is allowed to be 0.
|
||||
Also we close some new created streams, if they are non-restricted */
|
||||
// file Size will be set later by calling Seek() with Write()
|
||||
|
||||
/* the case (_absPos > _length) was processed above with SetSize(_absPos),
|
||||
so here it's expected. that we can create optional zero-size streams and then _streamIndex */
|
||||
RINOK(CreateStreams_If_Required(_streamIndex))
|
||||
|
||||
CVolStream &s = Streams[_streamIndex];
|
||||
|
||||
PRF(printf("\n%d, == Write : Pos = %u, RealSize = %u size =%u \n",
|
||||
_streamIndex, (unsigned)s.Pos, (unsigned)s.RealSize, size));
|
||||
|
||||
if (!s.Stream)
|
||||
{
|
||||
RINOK(ReOpenStream(_streamIndex))
|
||||
}
|
||||
if (_offsetPos != s.Pos)
|
||||
{
|
||||
RINOK(s.Stream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL))
|
||||
s.Pos = _offsetPos;
|
||||
}
|
||||
|
||||
UInt32 curSize = size;
|
||||
{
|
||||
const UInt64 rem = volSize - _offsetPos;
|
||||
if (curSize > rem)
|
||||
curSize = (UInt32)rem;
|
||||
}
|
||||
// curSize != 0
|
||||
UInt32 realProcessed = 0;
|
||||
|
||||
HRESULT hres = s.Stream->Write(data, curSize, &realProcessed);
|
||||
|
||||
data = (const void *)((const Byte *)data + realProcessed);
|
||||
size -= realProcessed;
|
||||
s.Pos += realProcessed;
|
||||
_offsetPos += realProcessed;
|
||||
_absPos += realProcessed;
|
||||
if (_length < _absPos)
|
||||
_length = _absPos;
|
||||
if (s.RealSize < _offsetPos)
|
||||
s.RealSize = _offsetPos;
|
||||
if (processedSize)
|
||||
*processedSize += realProcessed;
|
||||
|
||||
if (s.Pos == volSize)
|
||||
{
|
||||
bool isRestricted;
|
||||
if (volSize == 0)
|
||||
isRestricted = IsRestricted_Empty(s);
|
||||
else
|
||||
isRestricted = IsRestricted(s);
|
||||
if (!isRestricted)
|
||||
{
|
||||
const HRESULT res2 = CloseStream_and_FinalRename(_streamIndex);
|
||||
if (hres == S_OK)
|
||||
hres = res2;
|
||||
}
|
||||
_streamIndex++;
|
||||
_offsetPos = 0;
|
||||
}
|
||||
|
||||
RINOK(hres)
|
||||
if (realProcessed == 0 && curSize != 0)
|
||||
return E_FAIL;
|
||||
// break;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CMultiOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
PRF(printf("\n-- Seek seekOrigin=%u Seek =%u\n", seekOrigin, (unsigned)offset));
|
||||
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _absPos; break;
|
||||
case STREAM_SEEK_END: offset += _length; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
if ((UInt64)offset != _absPos)
|
||||
{
|
||||
_absPos = (UInt64)offset;
|
||||
_offsetPos = (UInt64)offset;
|
||||
_streamIndex = 0;
|
||||
}
|
||||
if (newPosition)
|
||||
*newPosition = (UInt64)offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
// result value will be saturated to (UInt32)(Int32)-1
|
||||
|
||||
unsigned CMultiOutStream::GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOffset) const
|
||||
{
|
||||
const unsigned last = Sizes.Size() - 1;
|
||||
for (unsigned i = 0; i < last; i++)
|
||||
{
|
||||
const UInt64 size = Sizes[i];
|
||||
if (offset < size)
|
||||
{
|
||||
relOffset = offset;
|
||||
return i;
|
||||
}
|
||||
offset -= size;
|
||||
}
|
||||
const UInt64 size = Sizes[last];
|
||||
const UInt64 v = offset / size;
|
||||
if (v >= ((UInt32)(Int32)-1) - last)
|
||||
return (UInt32)(Int32)-1; // saturation
|
||||
relOffset = offset - (unsigned)v * size;
|
||||
return last + (unsigned)(v);
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CMultiOutStream::SetRestriction(UInt64 begin, UInt64 end))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
// begin = end = 0; // for debug
|
||||
|
||||
PRF(printf("\n==================== CMultiOutStream::SetRestriction %u, %u\n", (unsigned)begin, (unsigned)end));
|
||||
if (begin > end)
|
||||
{
|
||||
// these value are FAILED values.
|
||||
return E_FAIL;
|
||||
// return E_INVALIDARG;
|
||||
/*
|
||||
// or we can ignore error with 3 ways: no change, non-restricted, saturation:
|
||||
end = begin; // non-restricted
|
||||
end = (UInt64)(Int64)-1; // saturation:
|
||||
return S_OK;
|
||||
*/
|
||||
}
|
||||
UInt64 b = _restrict_Begin;
|
||||
UInt64 e = _restrict_End;
|
||||
_restrict_Begin = begin;
|
||||
_restrict_End = end;
|
||||
|
||||
if (b == e) // if there were no restriction before
|
||||
return S_OK; // no work to derestrict now.
|
||||
|
||||
/* [b, e) is previous restricted region. So all volumes that
|
||||
intersect that [b, e) region are candidats for derestriction */
|
||||
|
||||
if (begin != end) // if there is new non-empty restricted region
|
||||
{
|
||||
/* Now we will try to reduce or change (b) and (e) bounds
|
||||
to reduce main loop that checks volumes for derestriction.
|
||||
We still use one big derestriction region in main loop, although
|
||||
in some cases we could have two smaller derestriction regions.
|
||||
Also usually restriction region cannot move back from previous start position,
|
||||
so (b <= begin) is expected here for normal cases */
|
||||
if (b == begin) // if same low bounds
|
||||
b = end; // we need to derestrict only after the end of new restricted region
|
||||
if (e == end) // if same high bounds
|
||||
e = begin; // we need to derestrict only before the begin of new restricted region
|
||||
}
|
||||
|
||||
if (b > e) // || b == (UInt64)(Int64)-1
|
||||
return S_OK;
|
||||
|
||||
/* Here we close finished volumes that are not restricted anymore.
|
||||
We close (low number) volumes at first. */
|
||||
|
||||
UInt64 offset;
|
||||
unsigned index = GetStreamIndex_for_Offset(b, offset);
|
||||
|
||||
for (; index < Streams.Size(); index++)
|
||||
{
|
||||
{
|
||||
const CVolStream &s = Streams[index];
|
||||
if (_length <= s.Start)
|
||||
break; // we don't close streams after _length
|
||||
// (_length > s.Start)
|
||||
const UInt64 volSize = GetVolSize_for_Stream(index);
|
||||
if (volSize == 0)
|
||||
{
|
||||
if (e < s.Start)
|
||||
break;
|
||||
// we don't close empty stream, if next byte [s.Start, s.Start] is restricted
|
||||
if (IsRestricted_Empty(s))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e <= s.Start)
|
||||
break;
|
||||
// we don't close non full streams
|
||||
if (_length - s.Start < volSize)
|
||||
break;
|
||||
// (volSize == s.RealSize) is expected here. So no need to check it
|
||||
// if (volSize != s.RealSize) break;
|
||||
if (IsRestricted(s))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
RINOK(CloseStream_and_FinalRename(index))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
160
CPP/7zip/Common/MultiOutStream.h
Executable file
160
CPP/7zip/Common/MultiOutStream.h
Executable file
@@ -0,0 +1,160 @@
|
||||
// MultiOutStream.h
|
||||
|
||||
#ifndef ZIP7_INC_MULTI_OUT_STREAM_H
|
||||
#define ZIP7_INC_MULTI_OUT_STREAM_H
|
||||
|
||||
#include "FileStreams.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CMultiOutStream
|
||||
, IOutStream
|
||||
, IStreamSetRestriction
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
|
||||
Z7_CLASS_NO_COPY(CMultiOutStream)
|
||||
|
||||
struct CVolStream
|
||||
{
|
||||
COutFileStream *StreamSpec;
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
UInt64 Start; // start pos of current Stream in global stream
|
||||
UInt64 Pos; // pos in current Stream
|
||||
UInt64 RealSize;
|
||||
int Next; // next older
|
||||
int Prev; // prev newer
|
||||
AString Postfix;
|
||||
|
||||
HRESULT SetSize2(UInt64 size)
|
||||
{
|
||||
const HRESULT res = Stream->SetSize(size);
|
||||
if (res == SZ_OK)
|
||||
RealSize = size;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
unsigned _streamIndex; // (_streamIndex >= Stream.Size()) is allowed in some internal code
|
||||
UInt64 _offsetPos; // offset relative to Streams[_streamIndex] volume. (_offsetPos >= volSize is allowed)
|
||||
UInt64 _absPos;
|
||||
UInt64 _length; // virtual Length
|
||||
UInt64 _absLimit;
|
||||
|
||||
CObjectVector<CVolStream> Streams;
|
||||
CRecordVector<UInt64> Sizes;
|
||||
|
||||
UInt64 _restrict_Begin;
|
||||
UInt64 _restrict_End;
|
||||
UInt64 _restrict_Global;
|
||||
|
||||
unsigned NumOpenFiles_AllowedMax;
|
||||
|
||||
// ----- Double Linked List -----
|
||||
|
||||
unsigned NumListItems;
|
||||
int Head; // newest
|
||||
int Tail; // oldest
|
||||
|
||||
void InitLinkedList()
|
||||
{
|
||||
Head = -1;
|
||||
Tail = -1;
|
||||
NumListItems = 0;
|
||||
}
|
||||
|
||||
void InsertToLinkedList(unsigned index)
|
||||
{
|
||||
{
|
||||
CVolStream &node = Streams[index];
|
||||
node.Next = Head;
|
||||
node.Prev = -1;
|
||||
}
|
||||
if (Head != -1)
|
||||
Streams[(unsigned)Head].Prev = (int)index;
|
||||
else
|
||||
{
|
||||
// if (Tail != -1) throw 1;
|
||||
Tail = (int)index;
|
||||
}
|
||||
Head = (int)index;
|
||||
NumListItems++;
|
||||
}
|
||||
|
||||
void RemoveFromLinkedList(unsigned index)
|
||||
{
|
||||
CVolStream &s = Streams[index];
|
||||
if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev;
|
||||
if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next;
|
||||
s.Next = -1; // optional
|
||||
s.Prev = -1; // optional
|
||||
NumListItems--;
|
||||
}
|
||||
|
||||
/*
|
||||
void Delete_LastStream_Records()
|
||||
{
|
||||
if (Streams.Back().Stream)
|
||||
RemoveFromLinkedList(Streams.Size() - 1);
|
||||
Streams.DeleteBack();
|
||||
}
|
||||
*/
|
||||
|
||||
UInt64 GetVolSize_for_Stream(unsigned i) const
|
||||
{
|
||||
const unsigned last = Sizes.Size() - 1;
|
||||
return Sizes[i < last ? i : last];
|
||||
}
|
||||
UInt64 GetGlobalOffset_for_NewStream() const
|
||||
{
|
||||
return Streams.Size() == 0 ? 0:
|
||||
Streams.Back().Start +
|
||||
GetVolSize_for_Stream(Streams.Size() - 1);
|
||||
}
|
||||
unsigned GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOffset) const;
|
||||
bool IsRestricted(const CVolStream &s) const;
|
||||
bool IsRestricted_Empty(const CVolStream &s) const
|
||||
{
|
||||
// (s) must be stream that has (VolSize == 0).
|
||||
// we treat empty stream as restricted, if next byte is restricted.
|
||||
if (s.Start < _restrict_Global)
|
||||
return true;
|
||||
return
|
||||
(_restrict_Begin != _restrict_End)
|
||||
&& (_restrict_Begin <= s.Start)
|
||||
&& (_restrict_Begin == s.Start || _restrict_End > s.Start);
|
||||
}
|
||||
// bool IsRestricted_for_Close(unsigned index) const;
|
||||
FString GetFilePath(unsigned index);
|
||||
|
||||
HRESULT CloseStream(unsigned index);
|
||||
HRESULT CloseStream_and_DeleteFile(unsigned index);
|
||||
HRESULT CloseStream_and_FinalRename(unsigned index);
|
||||
|
||||
HRESULT PrepareToOpenNew();
|
||||
HRESULT CreateNewStream(UInt64 newSize);
|
||||
HRESULT CreateStreams_If_Required(unsigned streamIndex);
|
||||
HRESULT ReOpenStream(unsigned streamIndex);
|
||||
HRESULT OptReOpen_and_SetSize(unsigned index, UInt64 size);
|
||||
|
||||
HRESULT Normalize_finalMode(bool finalMode);
|
||||
public:
|
||||
FString Prefix;
|
||||
CFiTime MTime;
|
||||
bool MTime_Defined;
|
||||
bool FinalVol_WasReopen;
|
||||
bool NeedDelete;
|
||||
|
||||
CMultiOutStream() {}
|
||||
~CMultiOutStream();
|
||||
void Init(const CRecordVector<UInt64> &sizes);
|
||||
bool SetMTime_Final(const CFiTime &mTime);
|
||||
UInt64 GetSize() const { return _length; }
|
||||
/* it makes final flushing, closes open files and renames to final name if required
|
||||
but it still keeps Streams array of all closed files.
|
||||
So we still can delete all files later, if required */
|
||||
HRESULT FinalFlush_and_CloseFiles(unsigned &numTotalVolumesRes);
|
||||
// Destruct object without exceptions
|
||||
HRESULT Destruct();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "OffsetStream.h"
|
||||
|
||||
HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
|
||||
@@ -13,12 +11,12 @@ HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
|
||||
return _stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
return _stream->Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
if (seekOrigin == STREAM_SEEK_SET)
|
||||
{
|
||||
@@ -27,13 +25,13 @@ STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new
|
||||
offset += _offset;
|
||||
}
|
||||
UInt64 absoluteNewPosition = 0; // =0 for gcc-10
|
||||
HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
|
||||
const HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
|
||||
if (newPosition)
|
||||
*newPosition = absoluteNewPosition - _offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)
|
||||
Z7_COM7F_IMF(COffsetOutStream::SetSize(UInt64 newSize))
|
||||
{
|
||||
return _stream->SetSize(_offset + newSize);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
// OffsetStream.h
|
||||
|
||||
#ifndef __OFFSET_STREAM_H
|
||||
#define __OFFSET_STREAM_H
|
||||
#ifndef ZIP7_INC_OFFSET_STREAM_H
|
||||
#define ZIP7_INC_OFFSET_STREAM_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class COffsetOutStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _offset;
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
COffsetOutStream
|
||||
, IOutStream
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
|
||||
CMyComPtr<IOutStream> _stream;
|
||||
UInt64 _offset;
|
||||
public:
|
||||
HRESULT Init(IOutStream *stream, UInt64 offset);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,18 +11,18 @@ bool COutBuffer::Create(UInt32 bufSize) throw()
|
||||
const UInt32 kMinBlockSize = 1;
|
||||
if (bufSize < kMinBlockSize)
|
||||
bufSize = kMinBlockSize;
|
||||
if (_buf != 0 && _bufSize == bufSize)
|
||||
if (_buf && _bufSize == bufSize)
|
||||
return true;
|
||||
Free();
|
||||
_bufSize = bufSize;
|
||||
_buf = (Byte *)::MidAlloc(bufSize);
|
||||
return (_buf != 0);
|
||||
return (_buf != NULL);
|
||||
}
|
||||
|
||||
void COutBuffer::Free() throw()
|
||||
{
|
||||
::MidFree(_buf);
|
||||
_buf = 0;
|
||||
_buf = NULL;
|
||||
}
|
||||
|
||||
void COutBuffer::Init() throw()
|
||||
@@ -32,7 +32,7 @@ void COutBuffer::Init() throw()
|
||||
_pos = 0;
|
||||
_processedSize = 0;
|
||||
_overDict = false;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
ErrorCode = S_OK;
|
||||
#endif
|
||||
}
|
||||
@@ -51,17 +51,17 @@ HRESULT COutBuffer::FlushPart() throw()
|
||||
// _streamPos < _bufSize
|
||||
UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos);
|
||||
HRESULT result = S_OK;
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
result = ErrorCode;
|
||||
#endif
|
||||
if (_buf2 != 0)
|
||||
if (_buf2)
|
||||
{
|
||||
memcpy(_buf2, _buf + _streamPos, size);
|
||||
_buf2 += size;
|
||||
}
|
||||
|
||||
if (_stream != 0
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
if (_stream
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
&& (ErrorCode == S_OK)
|
||||
#endif
|
||||
)
|
||||
@@ -85,14 +85,14 @@ HRESULT COutBuffer::FlushPart() throw()
|
||||
|
||||
HRESULT COutBuffer::Flush() throw()
|
||||
{
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
if (ErrorCode != S_OK)
|
||||
return ErrorCode;
|
||||
#endif
|
||||
|
||||
while (_streamPos != _pos)
|
||||
{
|
||||
HRESULT result = FlushPart();
|
||||
const HRESULT result = FlushPart();
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
@@ -101,8 +101,8 @@ HRESULT COutBuffer::Flush() throw()
|
||||
|
||||
void COutBuffer::FlushWithCheck()
|
||||
{
|
||||
HRESULT result = Flush();
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
const HRESULT result = Flush();
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// OutBuffer.h
|
||||
|
||||
#ifndef __OUT_BUFFER_H
|
||||
#define __OUT_BUFFER_H
|
||||
#ifndef ZIP7_INC_OUT_BUFFER_H
|
||||
#define ZIP7_INC_OUT_BUFFER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyException.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
#ifndef Z7_NO_EXCEPTIONS
|
||||
struct COutBufferException: public CSystemException
|
||||
{
|
||||
COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
@@ -29,11 +29,11 @@ protected:
|
||||
|
||||
HRESULT FlushPart() throw();
|
||||
public:
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
#ifdef Z7_NO_EXCEPTIONS
|
||||
HRESULT ErrorCode;
|
||||
#endif
|
||||
|
||||
COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {}
|
||||
COutBuffer(): _buf(NULL), _pos(0), _stream(NULL), _buf2(NULL) {}
|
||||
~COutBuffer() { Free(); }
|
||||
|
||||
bool Create(UInt32 bufSize) throw();
|
||||
|
||||
@@ -31,13 +31,13 @@ void COutMemStream::DetachData(CMemLockBlocks &blocks)
|
||||
|
||||
HRESULT COutMemStream::WriteToRealStream()
|
||||
{
|
||||
RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream));
|
||||
RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream))
|
||||
Blocks.Free(_memManager);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (_realStreamMode)
|
||||
return OutSeqStream->Write(data, size, processedSize);
|
||||
@@ -58,7 +58,7 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process
|
||||
size -= (UInt32)curSize;
|
||||
_curBlockPos += curSize;
|
||||
|
||||
UInt64 pos64 = GetPos();
|
||||
const UInt64 pos64 = GetPos();
|
||||
if (pos64 > Blocks.TotalSize)
|
||||
Blocks.TotalSize = pos64;
|
||||
if (_curBlockPos == _memManager->GetBlockSize())
|
||||
@@ -83,9 +83,9 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process
|
||||
case (WAIT_OBJECT_0 + 1):
|
||||
{
|
||||
_realStreamMode = true;
|
||||
RINOK(WriteToRealStream());
|
||||
RINOK(WriteToRealStream())
|
||||
UInt32 processedSize2;
|
||||
HRESULT res = OutSeqStream->Write(data, size, &processedSize2);
|
||||
const HRESULT res = OutSeqStream->Write(data, size, &processedSize2);
|
||||
if (processedSize)
|
||||
*processedSize += processedSize2;
|
||||
return res;
|
||||
@@ -103,7 +103,7 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process
|
||||
{
|
||||
if (waitResult == WAIT_FAILED)
|
||||
{
|
||||
DWORD res = ::GetLastError();
|
||||
const DWORD res = ::GetLastError();
|
||||
if (res != 0)
|
||||
return HRESULT_FROM_WIN32(res);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
@@ -145,7 +145,7 @@ STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::SetSize(UInt64 newSize)
|
||||
Z7_COM7F_IMF(COutMemStream::SetSize(UInt64 newSize))
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
// OutMemStream.h
|
||||
|
||||
#ifndef __OUT_MEM_STREAM_H
|
||||
#define __OUT_MEM_STREAM_H
|
||||
#ifndef ZIP7_INC_OUT_MEM_STREAM_H
|
||||
#define ZIP7_INC_OUT_MEM_STREAM_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "MemBlocks.h"
|
||||
|
||||
class COutMemStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
COutMemStream
|
||||
, IOutStream
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(ISequentialOutStream)
|
||||
|
||||
CMemBlockManagerMt *_memManager;
|
||||
unsigned _curBlockIndex;
|
||||
size_t _curBlockPos;
|
||||
unsigned _curBlockIndex;
|
||||
bool _realStreamMode;
|
||||
|
||||
bool _unlockEventWasSent;
|
||||
@@ -24,14 +26,13 @@ class COutMemStream:
|
||||
HRESULT StopWriteResult;
|
||||
CMemLockBlocks Blocks;
|
||||
|
||||
UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }
|
||||
|
||||
CMyComPtr<ISequentialOutStream> OutSeqStream;
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
|
||||
UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }
|
||||
|
||||
public:
|
||||
|
||||
|
||||
HRes CreateEvents(SYNC_PARAM_DECL(synchro))
|
||||
{
|
||||
WRes wres = StopWritingEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro));
|
||||
@@ -98,12 +99,6 @@ public:
|
||||
StopWriteResult = res;
|
||||
StopWritingEvent.Set();
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,13 +31,13 @@ HRESULT CMtCompressProgressMixer::SetRatioInfo(unsigned index, const UInt64 *inS
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
if (inSize)
|
||||
{
|
||||
UInt64 diff = *inSize - InSizes[index];
|
||||
const UInt64 diff = *inSize - InSizes[index];
|
||||
InSizes[index] = *inSize;
|
||||
TotalInSize += diff;
|
||||
}
|
||||
if (outSize)
|
||||
{
|
||||
UInt64 diff = *outSize - OutSizes[index];
|
||||
const UInt64 diff = *outSize - OutSizes[index];
|
||||
OutSizes[index] = *outSize;
|
||||
TotalOutSize += diff;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ HRESULT CMtCompressProgressMixer::SetRatioInfo(unsigned index, const UInt64 *inS
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
Z7_COM7F_IMF(CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
|
||||
{
|
||||
return _progress->SetRatioInfo(_index, inSize, outSize);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// ProgressMt.h
|
||||
|
||||
#ifndef __PROGRESSMT_H
|
||||
#define __PROGRESSMT_H
|
||||
#ifndef ZIP7_INC_PROGRESSMT_H
|
||||
#define ZIP7_INC_PROGRESSMT_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
@@ -24,12 +24,13 @@ public:
|
||||
HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CMtCompressProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMtCompressProgressMixer *_progress;
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
CMtCompressProgress
|
||||
, ICompressProgressInfo
|
||||
)
|
||||
unsigned _index;
|
||||
CMtCompressProgressMixer *_progress;
|
||||
public:
|
||||
void Init(CMtCompressProgressMixer *progress, unsigned index)
|
||||
{
|
||||
@@ -37,10 +38,6 @@ public:
|
||||
_index = index;
|
||||
}
|
||||
void Reinit() { _progress->Reinit(_index); }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include "ProgressUtils.h"
|
||||
|
||||
CLocalProgress::CLocalProgress():
|
||||
SendRatio(true),
|
||||
SendProgress(true),
|
||||
ProgressOffset(0),
|
||||
InSize(0),
|
||||
OutSize(0),
|
||||
SendRatio(true),
|
||||
SendProgress(true)
|
||||
OutSize(0)
|
||||
{}
|
||||
|
||||
void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
|
||||
@@ -20,7 +20,7 @@ void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
|
||||
_inSizeIsMain = inSizeIsMain;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
Z7_COM7F_IMF(CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
|
||||
{
|
||||
UInt64 inSize2 = InSize;
|
||||
UInt64 outSize2 = OutSize;
|
||||
@@ -32,7 +32,7 @@ STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *ou
|
||||
|
||||
if (SendRatio && _ratioProgress)
|
||||
{
|
||||
RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2));
|
||||
RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2))
|
||||
}
|
||||
|
||||
if (SendProgress)
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
// ProgressUtils.h
|
||||
|
||||
#ifndef __PROGRESS_UTILS_H
|
||||
#define __PROGRESS_UTILS_H
|
||||
#ifndef ZIP7_INC_PROGRESS_UTILS_H
|
||||
#define ZIP7_INC_PROGRESS_UTILS_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
class CLocalProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CLocalProgress
|
||||
, ICompressProgressInfo
|
||||
)
|
||||
public:
|
||||
bool SendRatio;
|
||||
bool SendProgress;
|
||||
private:
|
||||
bool _inSizeIsMain;
|
||||
CMyComPtr<IProgress> _progress;
|
||||
CMyComPtr<ICompressProgressInfo> _ratioProgress;
|
||||
bool _inSizeIsMain;
|
||||
public:
|
||||
UInt64 ProgressOffset;
|
||||
UInt64 InSize;
|
||||
UInt64 OutSize;
|
||||
bool SendRatio;
|
||||
bool SendProgress;
|
||||
|
||||
CLocalProgress();
|
||||
|
||||
void Init(IProgress *progress, bool inSizeIsMain);
|
||||
HRESULT SetCur();
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressProgressInfo)
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -111,5 +111,7 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_UI4 // kpidDeviceMinor
|
||||
VT_UI4,
|
||||
VT_UI4,
|
||||
VT_UI4 // kpidDevMinor
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// RegisterArc.h
|
||||
|
||||
#ifndef __REGISTER_ARC_H
|
||||
#define __REGISTER_ARC_H
|
||||
#ifndef ZIP7_INC_REGISTER_ARC_H
|
||||
#define ZIP7_INC_REGISTER_ARC_H
|
||||
|
||||
#include "../Archive/IArchive.h"
|
||||
|
||||
@@ -34,7 +34,7 @@ void RegisterArc(const CArcInfo *arcInfo) throw();
|
||||
|
||||
#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
#define IMP_CreateArcOut
|
||||
#define CreateArcOut NULL
|
||||
#else
|
||||
@@ -52,7 +52,7 @@ void RegisterArc(const CArcInfo *arcInfo) throw();
|
||||
|
||||
#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \
|
||||
IMP_CreateArcIn_2(cls) \
|
||||
REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, 0, CreateArc, NULL, isArc)
|
||||
REGISTER_ARC_R(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, 0, CreateArc, NULL, isArc)
|
||||
|
||||
#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \
|
||||
IMP_CreateArcIn_2(cls) \
|
||||
@@ -68,12 +68,12 @@ void RegisterArc(const CArcInfo *arcInfo) throw();
|
||||
#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, tf, isArc) \
|
||||
IMP_CreateArcIn \
|
||||
IMP_CreateArcOut \
|
||||
REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc)
|
||||
REGISTER_ARC_R(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc)
|
||||
|
||||
#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, tf, isArc) \
|
||||
IMP_CreateArcIn \
|
||||
IMP_CreateArcOut \
|
||||
REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) \
|
||||
REGISTER_ARC_V(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) \
|
||||
struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \
|
||||
static CRegisterArcDecSig g_RegisterArc;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// RegisterCodec.h
|
||||
|
||||
#ifndef __REGISTER_CODEC_H
|
||||
#define __REGISTER_CODEC_H
|
||||
#ifndef ZIP7_INC_REGISTER_CODEC_H
|
||||
#define ZIP7_INC_REGISTER_CODEC_H
|
||||
|
||||
#include "../Common/MethodId.h"
|
||||
|
||||
@@ -37,7 +37,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw();
|
||||
#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] =
|
||||
|
||||
#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
|
||||
REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
|
||||
REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_CodecsInfo); i++) \
|
||||
RegisterCodec(&g_CodecsInfo[i]); }}; \
|
||||
static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
|
||||
|
||||
@@ -48,7 +48,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw();
|
||||
REGISTER_CODEC(x)
|
||||
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
#define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_CODEC_CREATE(CreateDec, clsDec) \
|
||||
REGISTER_CODEC_2(x, CreateDec, NULL, id, name)
|
||||
@@ -71,7 +71,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw();
|
||||
REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \
|
||||
REGISTER_CODEC(x)
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
#ifdef Z7_EXTRACT_ONLY
|
||||
#define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
|
||||
REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \
|
||||
REGISTER_FILTER(x, x ## _CreateDec, NULL, id, name)
|
||||
@@ -97,7 +97,7 @@ void RegisterHasher(const CHasherInfo *hasher) throw();
|
||||
#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x
|
||||
|
||||
#define REGISTER_HASHER(cls, id, name, size) \
|
||||
STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \
|
||||
Z7_COM7F_IMF2(UInt32, cls::GetDigestSize()) { return size; } \
|
||||
static IHasher *CreateHasherSpec() { return new cls(); } \
|
||||
static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \
|
||||
struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,51 +6,44 @@
|
||||
|
||||
#include "StreamBinder.h"
|
||||
|
||||
class CBinderInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CBinderInStream
|
||||
, ISequentialInStream
|
||||
)
|
||||
CStreamBinder *_binder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
~CBinderInStream() { _binder->CloseRead_CallOnce(); }
|
||||
CBinderInStream(CStreamBinder *binder): _binder(binder) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{ return _binder->Read(data, size, processedSize); }
|
||||
|
||||
class CBinderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CBinderOutStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
CStreamBinder *_binder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
~CBinderOutStream() { _binder->CloseWrite(); }
|
||||
CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
|
||||
};
|
||||
|
||||
STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{ return _binder->Write(data, size, processedSize); }
|
||||
|
||||
|
||||
static HRESULT Event__Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event)
|
||||
static HRESULT Event_Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event)
|
||||
{
|
||||
WRes wres;
|
||||
if (event.IsCreated())
|
||||
wres = event.Reset();
|
||||
else
|
||||
wres = event.Create();
|
||||
const WRes wres = event.CreateIfNotCreated_Reset();
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
}
|
||||
|
||||
HRESULT CStreamBinder::Create_ReInit()
|
||||
{
|
||||
RINOK(Event__Create_or_Reset(_canRead_Event));
|
||||
// RINOK(Event__Create_or_Reset(_canWrite_Event));
|
||||
RINOK(Event_Create_or_Reset(_canRead_Event))
|
||||
// RINOK(Event_Create_or_Reset(_canWrite_Event))
|
||||
|
||||
// _canWrite_Semaphore.Close();
|
||||
// we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// StreamBinder.h
|
||||
|
||||
#ifndef __STREAM_BINDER_H
|
||||
#define __STREAM_BINDER_H
|
||||
#ifndef ZIP7_INC_STREAM_BINDER_H
|
||||
#define ZIP7_INC_STREAM_BINDER_H
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "StreamObjects.h"
|
||||
|
||||
STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -26,7 +24,7 @@ STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -43,7 +41,7 @@ STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -61,7 +59,7 @@ STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
@@ -99,8 +97,8 @@ void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequential
|
||||
|
||||
void CByteDynBuffer::Free() throw()
|
||||
{
|
||||
free(_buf);
|
||||
_buf = 0;
|
||||
MyFree(_buf);
|
||||
_buf = NULL;
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
@@ -108,11 +106,10 @@ bool CByteDynBuffer::EnsureCapacity(size_t cap) throw()
|
||||
{
|
||||
if (cap <= _capacity)
|
||||
return true;
|
||||
size_t delta = _capacity / 4;
|
||||
size_t cap2 = _capacity + delta;
|
||||
const size_t cap2 = _capacity + _capacity / 4;
|
||||
if (cap < cap2)
|
||||
cap = cap2;
|
||||
Byte *buf = (Byte *)realloc(_buf, cap);
|
||||
Byte *buf = (Byte *)MyRealloc(_buf, cap);
|
||||
if (!buf)
|
||||
return false;
|
||||
_buf = buf;
|
||||
@@ -135,7 +132,7 @@ void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
|
||||
dest.CopyFrom((const Byte *)_buffer, _size);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -151,7 +148,7 @@ STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *p
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
size_t rem = _size - _pos;
|
||||
if (rem > size)
|
||||
@@ -166,7 +163,7 @@ STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *p
|
||||
return (rem != 0 || size == 0) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Write(data, size, &realProcessedSize);
|
||||
@@ -216,12 +213,12 @@ void CCachedInStream::Init(UInt64 size) throw()
|
||||
{
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
size_t numBlocks = (size_t)1 << _numBlocksLog;
|
||||
const size_t numBlocks = (size_t)1 << _numBlocksLog;
|
||||
for (size_t i = 0; i < numBlocks; i++)
|
||||
_tags[i] = kEmptyTag;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
Z7_COM7F_IMF(CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
@@ -231,7 +228,7 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
UInt64 rem = _size - _pos;
|
||||
const UInt64 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
@@ -245,12 +242,12 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
if (_tags[cacheIndex] != cacheTag)
|
||||
{
|
||||
_tags[cacheIndex] = kEmptyTag;
|
||||
UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
|
||||
const UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
|
||||
size_t blockSize = (size_t)1 << _blockSizeLog;
|
||||
if (blockSize > remInBlock)
|
||||
blockSize = (size_t)remInBlock;
|
||||
|
||||
RINOK(ReadBlock(cacheTag, p, blockSize));
|
||||
RINOK(ReadBlock(cacheTag, p, blockSize))
|
||||
|
||||
_tags[cacheIndex] = cacheTag;
|
||||
}
|
||||
@@ -275,7 +272,7 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
Z7_COM7F_IMF(CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// StreamObjects.h
|
||||
|
||||
#ifndef __STREAM_OBJECTS_H
|
||||
#define __STREAM_OBJECTS_H
|
||||
#ifndef ZIP7_INC_STREAM_OBJECTS_H
|
||||
#define ZIP7_INC_STREAM_OBJECTS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
@@ -9,35 +9,27 @@
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CBufferInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CBufferInStream
|
||||
)
|
||||
UInt64 _pos;
|
||||
public:
|
||||
CByteBuffer Buf;
|
||||
void Init() { _pos = 0; }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
|
||||
struct CReferenceBuf:
|
||||
public IUnknown,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_0(
|
||||
CReferenceBuf
|
||||
)
|
||||
public:
|
||||
CByteBuffer Buf;
|
||||
MY_UNKNOWN_IMP
|
||||
};
|
||||
|
||||
|
||||
class CBufInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_IInStream(
|
||||
CBufInStream
|
||||
)
|
||||
const Byte *_data;
|
||||
UInt64 _pos;
|
||||
size_t _size;
|
||||
@@ -52,9 +44,8 @@ public:
|
||||
}
|
||||
void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); }
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
// Seek() is allowed here. So reading order could be changed
|
||||
bool WasFinished() const { return _pos == _size; }
|
||||
};
|
||||
|
||||
|
||||
@@ -64,13 +55,13 @@ inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequential
|
||||
{ Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); }
|
||||
|
||||
|
||||
class CByteDynBuffer
|
||||
class CByteDynBuffer Z7_final
|
||||
{
|
||||
size_t _capacity;
|
||||
Byte *_buf;
|
||||
CLASS_NO_COPY(CByteDynBuffer);
|
||||
Z7_CLASS_NO_COPY(CByteDynBuffer)
|
||||
public:
|
||||
CByteDynBuffer(): _capacity(0), _buf(NULL) {};
|
||||
CByteDynBuffer(): _capacity(0), _buf(NULL) {}
|
||||
// there is no copy constructor. So don't copy this object.
|
||||
~CByteDynBuffer() { Free(); }
|
||||
void Free() throw();
|
||||
@@ -81,10 +72,10 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class CDynBufSeqOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CDynBufSeqOutStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
CByteDynBuffer _buffer;
|
||||
size_t _size;
|
||||
public:
|
||||
@@ -95,16 +86,13 @@ public:
|
||||
void CopyToBuffer(CByteBuffer &dest) const;
|
||||
Byte *GetBufPtrForWriting(size_t addSize);
|
||||
void UpdateSize(size_t addSize) { _size += addSize; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
|
||||
class CBufPtrSeqOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CBufPtrSeqOutStream
|
||||
, ISequentialOutStream
|
||||
)
|
||||
Byte *_buffer;
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
@@ -116,25 +104,19 @@ public:
|
||||
_size = size;
|
||||
}
|
||||
size_t GetPos() const { return _pos; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
|
||||
class CSequentialOutStreamSizeCount:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CSequentialOutStreamSizeCount
|
||||
, ISequentialOutStream
|
||||
)
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialOutStream)
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
|
||||
@@ -142,6 +124,8 @@ class CCachedInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream)
|
||||
|
||||
UInt64 *_tags;
|
||||
Byte *_data;
|
||||
size_t _dataSize;
|
||||
@@ -153,14 +137,10 @@ protected:
|
||||
virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;
|
||||
public:
|
||||
CCachedInStream(): _tags(NULL), _data(NULL) {}
|
||||
virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!
|
||||
virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (Release() calls it) !!!
|
||||
void Free() throw();
|
||||
bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw();
|
||||
void Init(UInt64 size) throw();
|
||||
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,10 +2,55 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
|
||||
static const UInt32 kBlockSize = ((UInt32)1 << 31);
|
||||
|
||||
|
||||
HRESULT InStream_SeekToBegin(IInStream *stream) throw()
|
||||
{
|
||||
return InStream_SeekSet(stream, 0);
|
||||
}
|
||||
|
||||
|
||||
HRESULT InStream_AtBegin_GetSize(IInStream *stream, UInt64 &sizeRes) throw()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IStreamGetSize,
|
||||
streamGetSize, stream)
|
||||
if (streamGetSize && streamGetSize->GetSize(&sizeRes) == S_OK)
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
const HRESULT hres = InStream_GetSize_SeekToEnd(stream, sizeRes);
|
||||
const HRESULT hres2 = InStream_SeekToBegin(stream);
|
||||
return hres != S_OK ? hres : hres2;
|
||||
}
|
||||
|
||||
|
||||
HRESULT InStream_GetPos_GetSize(IInStream *stream, UInt64 &curPosRes, UInt64 &sizeRes) throw()
|
||||
{
|
||||
RINOK(InStream_GetPos(stream, curPosRes))
|
||||
#ifdef _WIN32
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IStreamGetSize,
|
||||
streamGetSize, stream)
|
||||
if (streamGetSize && streamGetSize->GetSize(&sizeRes) == S_OK)
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
const HRESULT hres = InStream_GetSize_SeekToEnd(stream, sizeRes);
|
||||
const HRESULT hres2 = InStream_SeekSet(stream, curPosRes);
|
||||
return hres != S_OK ? hres : hres2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw()
|
||||
{
|
||||
size_t size = *processedSize;
|
||||
@@ -18,7 +63,7 @@ HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSiz
|
||||
*processedSize += processedSizeLoc;
|
||||
data = (void *)((Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
RINOK(res);
|
||||
RINOK(res)
|
||||
if (processedSizeLoc == 0)
|
||||
return S_OK;
|
||||
}
|
||||
@@ -28,14 +73,14 @@ HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSiz
|
||||
HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw()
|
||||
{
|
||||
size_t processedSize = size;
|
||||
RINOK(ReadStream(stream, data, &processedSize));
|
||||
RINOK(ReadStream(stream, data, &processedSize))
|
||||
return (size == processedSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw()
|
||||
{
|
||||
size_t processedSize = size;
|
||||
RINOK(ReadStream(stream, data, &processedSize));
|
||||
RINOK(ReadStream(stream, data, &processedSize))
|
||||
return (size == processedSize) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
@@ -48,7 +93,7 @@ HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size)
|
||||
HRESULT res = stream->Write(data, curSize, &processedSizeLoc);
|
||||
data = (const void *)((const Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
RINOK(res);
|
||||
RINOK(res)
|
||||
if (processedSizeLoc == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
// StreamUtils.h
|
||||
|
||||
#ifndef __STREAM_UTILS_H
|
||||
#define __STREAM_UTILS_H
|
||||
#ifndef ZIP7_INC_STREAM_UTILS_H
|
||||
#define ZIP7_INC_STREAM_UTILS_H
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
inline HRESULT InStream_SeekSet(IInStream *stream, UInt64 offset) throw()
|
||||
{ return stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); }
|
||||
inline HRESULT InStream_GetPos(IInStream *stream, UInt64 &curPosRes) throw()
|
||||
{ return stream->Seek(0, STREAM_SEEK_CUR, &curPosRes); }
|
||||
inline HRESULT InStream_GetSize_SeekToEnd(IInStream *stream, UInt64 &sizeRes) throw()
|
||||
{ return stream->Seek(0, STREAM_SEEK_END, &sizeRes); }
|
||||
|
||||
HRESULT InStream_SeekToBegin(IInStream *stream) throw();
|
||||
HRESULT InStream_AtBegin_GetSize(IInStream *stream, UInt64 &size) throw();
|
||||
HRESULT InStream_GetPos_GetSize(IInStream *stream, UInt64 &curPosRes, UInt64 &sizeRes) throw();
|
||||
|
||||
inline HRESULT InStream_GetSize_SeekToBegin(IInStream *stream, UInt64 &sizeRes) throw()
|
||||
{
|
||||
RINOK(InStream_SeekToBegin(stream))
|
||||
return InStream_AtBegin_GetSize(stream, sizeRes);
|
||||
}
|
||||
|
||||
|
||||
HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw();
|
||||
HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw();
|
||||
HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// UniqBlocks.h
|
||||
|
||||
#ifndef __UNIQ_BLOCKS_H
|
||||
#define __UNIQ_BLOCKS_H
|
||||
#ifndef ZIP7_INC_UNIQ_BLOCKS_H
|
||||
#define ZIP7_INC_UNIQ_BLOCKS_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
@@ -11,7 +11,7 @@ static THREAD_FUNC_DECL CoderThread(void *p)
|
||||
CVirtThread *t = (CVirtThread *)p;
|
||||
t->StartEvent.Lock();
|
||||
if (t->Exit)
|
||||
return 0;
|
||||
return THREAD_FUNC_RET_ZERO;
|
||||
t->Execute();
|
||||
t->FinishedEvent.Set();
|
||||
}
|
||||
@@ -19,8 +19,8 @@ static THREAD_FUNC_DECL CoderThread(void *p)
|
||||
|
||||
WRes CVirtThread::Create()
|
||||
{
|
||||
RINOK_WRes(StartEvent.CreateIfNotCreated_Reset());
|
||||
RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset());
|
||||
RINOK_WRes(StartEvent.CreateIfNotCreated_Reset())
|
||||
RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset())
|
||||
// StartEvent.Reset();
|
||||
// FinishedEvent.Reset();
|
||||
Exit = false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// VirtThread.h
|
||||
|
||||
#ifndef __VIRT_THREAD_H
|
||||
#define __VIRT_THREAD_H
|
||||
#ifndef ZIP7_INC_VIRT_THREAD_H
|
||||
#define ZIP7_INC_VIRT_THREAD_H
|
||||
|
||||
#include "../../Windows/Synchronization.h"
|
||||
#include "../../Windows/Thread.h"
|
||||
@@ -13,7 +13,7 @@ struct CVirtThread
|
||||
NWindows::CThread Thread;
|
||||
bool Exit;
|
||||
|
||||
~CVirtThread() { WaitThreadFinish(); }
|
||||
virtual ~CVirtThread() { WaitThreadFinish(); }
|
||||
void WaitThreadFinish(); // call it in destructor of child class !
|
||||
WRes Create();
|
||||
WRes Start();
|
||||
|
||||
Reference in New Issue
Block a user