This commit is contained in:
Igor Pavlov
2023-12-22 17:17:05 +00:00
committed by Kornel
parent ec44a8a070
commit a36c48cece
954 changed files with 42199 additions and 25482 deletions

View File

@@ -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);

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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"

View File

@@ -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;

View File

@@ -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

View File

@@ -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); }

View File

@@ -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();
};

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;
}
*/

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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"

View File

@@ -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 &param = 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
{

View File

@@ -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"

View 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
View 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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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();

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
};

View File

@@ -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;

View File

@@ -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); }}; \

View File

@@ -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

View File

@@ -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()

View File

@@ -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"

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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"

View File

@@ -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;

View File

@@ -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();