diff options
Diffstat (limited to 'CPP/7zip/Common')
25 files changed, 1155 insertions, 565 deletions
diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp index e5e09327..75074ad8 100644 --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -10,25 +10,40 @@ #include "FilterCoder.h" #include "RegisterCodec.h" -static const unsigned int kNumCodecsMax = 64; -unsigned int g_NumCodecs = 0; +static const unsigned kNumCodecsMax = 64; +unsigned g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; + +// We use g_ExternalCodecs in other stages. +/* +#ifdef EXTERNAL_CODECS +extern CExternalCodecs g_ExternalCodecs; +#define CHECK_GLOBAL_CODECS \ + if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs; +#endif +*/ + +#define CHECK_GLOBAL_CODECS + void RegisterCodec(const CCodecInfo *codecInfo) throw() { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } -static const unsigned int kNumHashersMax = 16; -unsigned int g_NumHashers = 0; +static const unsigned kNumHashersMax = 16; +unsigned g_NumHashers = 0; const CHasherInfo *g_Hashers[kNumHashersMax]; + void RegisterHasher(const CHasherInfo *hashInfo) throw() { if (g_NumHashers < kNumHashersMax) g_Hashers[g_NumHashers++] = hashInfo; } + #ifdef EXTERNAL_CODECS + static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; @@ -55,102 +70,130 @@ static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, return S_OK; } -HRESULT CExternalCodecs::LoadCodecs() +HRESULT CExternalCodecs::Load() { + Codecs.Clear(); + Hashers.Clear(); + if (GetCodecs) { + CCodecInfoEx info; + + UString s; UInt32 num; - RINOK(GetCodecs->GetNumberOfMethods(&num)); + RINOK(GetCodecs->GetNumMethods(&num)); + for (UInt32 i = 0; i < num; i++) { - CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)); - // if (prop.vt != VT_BSTR) - // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); - // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) continue; // old Interface info.Id = prop.uhVal.QuadPart; + prop.Clear(); + info.Name.Empty(); RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) - info.Name = prop.bstrVal; + info.Name.SetFromWStr_if_Ascii(prop.bstrVal); else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; + continue; - RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams)); - RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams)); + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams)); + { + UInt32 numUnpackStreams = 1; + 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)); Codecs.Add(info); } } + if (GetHashers) { UInt32 num = GetHashers->GetNumHashers(); + CHasherInfoEx info; + for (UInt32 i = 0; i < num; i++) { - CHasherInfoEx info; NWindows::NCOM::CPropVariant prop; + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) continue; info.Id = prop.uhVal.QuadPart; + prop.Clear(); + info.Name.Empty(); RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) - info.Name = prop.bstrVal; + info.Name.SetFromWStr_if_Ascii(prop.bstrVal); else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; + continue; Hashers.Add(info); } } + return S_OK; } #endif -bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) + +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId, UInt32 &numStreams) { - UInt32 i; + unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; - if (name.IsEqualToNoCase(codec.Name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; - numInStreams = codec.NumInStreams; - numOutStreams = 1; + numStreams = codec.NumStreams; return true; } } + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; - if (codec.Name.IsEqualToNoCase(name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; - numInStreams = codec.NumInStreams; - numOutStreams = codec.NumOutStreams; + numStreams = codec.NumStreams; return true; } } + #endif + return false; } -bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, UString &name) +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name) { - UInt32 i; + name.Empty(); + + unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; @@ -160,9 +203,13 @@ bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS return true; } } + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (methodId == codec.Id) @@ -171,62 +218,79 @@ bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS return true; } } + #endif + return false; } -bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, - CMethodId &methodId) +bool FindHashMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId) { - UInt32 i; + unsigned i; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; - if (name.IsEqualToNoCase(codec.Name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; return true; } } + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) { const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; - if (codec.Name.IsEqualToNoCase(name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; return true; } } + #endif + return false; } -void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS +void GetHashMethods( + DECL_EXTERNAL_CODECS_LOC_VARS CRecordVector<CMethodId> &methods) { methods.ClearAndSetSize(g_NumHashers); - UInt32 i; + unsigned i; for (i = 0; i < g_NumHashers; i++) methods[i] = (*g_Hashers[i]).Id; + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) methods.Add(__externalCodecs->Hashers[i].Id); + #endif } HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode, bool onlyCoder) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter, + CCreatedCoder &cod) { - UInt32 i; + cod.IsExternal = false; + cod.IsFilter = false; + cod.NumStreams = 1; + + unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; @@ -238,9 +302,9 @@ HRESULT CreateCoder( { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; - else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; - else coder2 = (ICompressCoder2 *)p; - break; + else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; + else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } + return S_OK; } } else @@ -248,16 +312,21 @@ HRESULT CreateCoder( { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; - else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; - else coder2 = (ICompressCoder2 *)p; - break; + else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; + else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } + return S_OK; } } } #ifdef EXTERNAL_CODECS - if (!filter && !coder && !coder2 && __externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + { + cod.IsExternal = true; + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (codec.Id == methodId) @@ -266,125 +335,126 @@ HRESULT CreateCoder( { if (codec.EncoderIsAssigned) { - if (codec.IsSimpleCodec()) - { - HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); - if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) - return result; - if (!coder) - { - RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); - } - } - else + if (codec.NumStreams == 1) { - RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); + 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); } - break; + cod.NumStreams = codec.NumStreams; + return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); } } else if (codec.DecoderIsAssigned) { - if (codec.IsSimpleCodec()) + if (codec.NumStreams == 1) { - HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); - if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) - return result; - if (!coder) - { - RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); - } + 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); } - else - { - RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); - } - break; + cod.NumStreams = codec.NumStreams; + return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); } } } + } #endif - if (onlyCoder && filter) - { - CFilterCoder *coderSpec = new CFilterCoder; - coder = coderSpec; - coderSpec->Filter = filter; - } return S_OK; } HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CCreatedCoder &cod) { CMyComPtr<ICompressFilter> filter; - return CreateCoder( - EXTERNAL_CODECS_LOC_VARS - methodId, - filter, coder, coder2, encode, true); + HRESULT res = CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + filter, cod); + + if (filter) + { + cod.IsFilter = true; + CFilterCoder *coderSpec = new CFilterCoder(encode); + cod.Coder = coderSpec; + coderSpec->Filter = filter; + } + + return res; } HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, bool encode) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressCoder> &coder) { - CMyComPtr<ICompressFilter> filter; - CMyComPtr<ICompressCoder2> coder2; - return CreateCoder( - EXTERNAL_CODECS_LOC_VARS - methodId, - coder, coder2, encode); + CCreatedCoder cod; + HRESULT res = CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + cod); + coder = cod.Coder; + return res; } HRESULT CreateFilter( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - bool encode) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter) { - CMyComPtr<ICompressCoder> coder; - CMyComPtr<ICompressCoder2> coder2; + CCreatedCoder cod; return CreateCoder( - EXTERNAL_CODECS_LOC_VARS - methodId, - filter, coder, coder2, encode, false); + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + filter, cod); } + HRESULT CreateHasher( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - UString &name, - CMyComPtr<IHasher> &hasher) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr<IHasher> &hasher) { - UInt32 i; + name.Empty(); + + unsigned i; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; if (codec.Id == methodId) { - hasher = (IHasher *)codec.CreateHasher(); + hasher = codec.CreateHasher(); name = codec.Name; break; } } #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (!hasher && __externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) { const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; if (codec.Id == methodId) { name = codec.Name; - return __externalCodecs->GetHashers->CreateHasher(i, &hasher); + return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher); } } + #endif return S_OK; diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h index 50a68ce1..f06064b6 100644 --- a/CPP/7zip/Common/CreateCoder.h +++ b/CPP/7zip/Common/CreateCoder.h @@ -5,29 +5,44 @@ #include "../../Common/MyCom.h" #include "../../Common/MyString.h" + #include "../ICoder.h" #include "MethodId.h" +/* + if 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 + 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. + + CExternalCodecs contains information about codecs and interfaces to create them. + + The order of codecs: + 1) Internal codecs + 2) External codecs +*/ + #ifdef EXTERNAL_CODECS struct CCodecInfoEx { - UString Name; CMethodId Id; - UInt32 NumInStreams; - UInt32 NumOutStreams; + AString Name; + UInt32 NumStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; - bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; struct CHasherInfoEx { - UString Name; CMethodId Id; + AString Name; }; #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, @@ -35,7 +50,7 @@ struct CHasherInfoEx #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ - COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.LoadCodecs(); COM_TRY_END } + COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) struct CExternalCodecs @@ -46,13 +61,36 @@ struct CExternalCodecs CObjectVector<CCodecInfoEx> Codecs; CObjectVector<CHasherInfoEx> Hashers; - HRESULT LoadCodecs(); + bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; } + + HRESULT Load(); + + void ClearAndRelease() + { + Hashers.Clear(); + Codecs.Clear(); + GetHashers.Release(); + GetCodecs.Release(); + } + + ~CExternalCodecs() + { + GetHashers.Release(); + GetCodecs.Release(); + } }; -#define EXTERNAL_CODECS_VARS2 &__externalCodecs +extern CExternalCodecs g_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 EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, + +#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 @@ -68,7 +106,9 @@ struct CExternalCodecs #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS -#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 +#define EXTERNAL_CODECS_VARS +#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 @@ -76,52 +116,67 @@ struct CExternalCodecs #endif + + + bool FindMethod( - DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId, UInt32 &numStreams); bool FindMethod( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, UString &name); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name); bool FindHashMethod( - DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, CMethodId &methodId); + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId); void GetHashMethods( - DECL_EXTERNAL_CODECS_LOC_VARS - CRecordVector<CMethodId> &methods); + DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector<CMethodId> &methods); + + +struct CCreatedCoder +{ + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ICompressCoder2> Coder2; + + bool IsExternal; + bool IsFilter; // = true, if Coder was created from filter + UInt32 NumStreams; + + // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {} +}; + HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode, bool onlyCoder); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter, + CCreatedCoder &cod); HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CCreatedCoder &cod); HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, bool encode); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressCoder> &coder); HRESULT CreateFilter( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - bool encode); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter); HRESULT CreateHasher( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - UString &name, - CMyComPtr<IHasher> &hacher); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr<IHasher> &hasher); #endif diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index 958360fa..d186e599 100644 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -12,44 +12,40 @@ using namespace NWindows; static bool MakeAutoName(const FString &name, - const FString &extension, unsigned value, FString &path) + const FString &extension, UInt32 value, FString &path) { - FChar number[16]; - ConvertUInt32ToString(value, number); + char temp[16]; + ConvertUInt32ToString(value, temp); path = name; - path += number; + path.AddAscii(temp); path += extension; return NFile::NFind::DoesFileOrDirExist(path); } -bool AutoRenamePath(FString &fullProcessedPath) +bool AutoRenamePath(FString &path) { - FString path; - int dotPos = fullProcessedPath.ReverseFind(FTEXT('.')); + int dotPos = path.ReverseFind_Dot(); + int slashPos = path.ReverseFind_PathSepar(); - int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); - #ifdef _WIN32 - int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); - slashPos = MyMax(slashPos, slash1Pos); - #endif - - FString name, extension; - if (dotPos > slashPos && dotPos > 0) + FString name = path; + FString extension; + if (dotPos > slashPos + 1) { - name.SetFrom(fullProcessedPath, dotPos); - extension = fullProcessedPath.Ptr(dotPos); + name.DeleteFrom(dotPos); + extension = path.Ptr(dotPos); } - else - name = fullProcessedPath; - name += L'_'; - unsigned left = 1, right = (1 << 30); + name += FTEXT('_'); + + FString temp; + + UInt32 left = 1, right = ((UInt32)1 << 30); while (left != right) { - unsigned mid = (left + right) / 2; - if (MakeAutoName(name, extension, mid, path)) + UInt32 mid = (left + right) / 2; + if (MakeAutoName(name, extension, mid, temp)) left = mid + 1; else right = mid; } - return !MakeAutoName(name, extension, right, fullProcessedPath); + return !MakeAutoName(name, extension, right, path); } diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index 1523fad1..f3a322fc 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -29,25 +29,29 @@ static inline HRESULT ConvertBoolToHRESULT(bool result) #endif } -#ifdef SUPPORT_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; CInFileStream::CInFileStream(): + #ifdef SUPPORT_DEVICE_FILE VirtPos(0), PhyPos(0), Buf(0), BufSize(0), - SupportHardLinks(false) + #endif + SupportHardLinks(false), + Callback(NULL), + CallbackRef(0) { } -#endif - CInFileStream::~CInFileStream() { #ifdef SUPPORT_DEVICE_FILE MidFree(Buf); #endif + + if (Callback) + Callback->InFileStream_On_Destroy(CallbackRef); } STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -148,19 +152,37 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) bool result = File.ReadPart(data, size, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; + #ifdef SUPPORT_DEVICE_FILE VirtPos += realProcessedSize; PhyPos += realProcessedSize; #endif - return ConvertBoolToHRESULT(result); - + + if (result) + return S_OK; + + { + DWORD error = ::GetLastError(); + + if (Callback) + return Callback->InFileStream_On_Error(CallbackRef, error); + if (error == 0) + return E_FAIL; + + return HRESULT_FROM_WIN32(error); + } + #else if (processedSize) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) + { + if (Callback) + return Callback->InFileStream_On_Error(CallbackRef, E_FAIL); return E_FAIL; + } if (processedSize) *processedSize = (UInt32)res; return S_OK; @@ -321,7 +343,7 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces #ifdef USE_WIN_FILE UInt32 realProcessedSize; - bool result = File.WritePart(data, size, realProcessedSize); + bool result = File.Write(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; @@ -346,6 +368,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo { if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; + #ifdef USE_WIN_FILE UInt64 realNewPosition; @@ -369,6 +392,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) { #ifdef USE_WIN_FILE + UInt64 currentPos; if (!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; @@ -376,12 +400,21 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; + #else + return E_FAIL; + #endif } +HRESULT COutFileStream::GetSize(UInt64 *size) +{ + return ConvertBoolToHRESULT(File.GetLength(*size)); +} + #ifdef UNDER_CE + STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t s2 = fwrite(data, 1, size, stdout); @@ -389,13 +422,16 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro *processedSize = s2; return (s2 == size) ? S_OK : E_FAIL; } + #else + STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; #ifdef _WIN32 + UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) @@ -407,6 +443,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); + _size += realProcessedSize; size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if (processedSize) @@ -417,18 +454,21 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro #else ssize_t res; + do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); + if (res == -1) return E_FAIL; + + _size += (size_t)res; if (processedSize) *processedSize = (UInt32)res; return S_OK; - return S_OK; #endif } diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index 971366e9..ef2986fd 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -19,6 +19,18 @@ #include "../IStream.h" +#ifdef _WIN32 +typedef UINT_PTR My_UINT_PTR; +#else +typedef UINT My_UINT_PTR; +#endif + +struct IInFileStream_Callback +{ + virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0; + virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0; +}; + class CInFileStream: public IInStream, public IStreamGetSize, @@ -45,12 +57,13 @@ public: #endif bool SupportHardLinks; - + + IInFileStream_Callback *Callback; + My_UINT_PTR CallbackRef; + virtual ~CInFileStream(); - #ifdef SUPPORT_DEVICE_FILE CInFileStream(); - #endif bool Open(CFSTR fileName) { @@ -132,15 +145,20 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(UInt64 newSize); + + HRESULT GetSize(UInt64 *size); }; class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { + 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); }; diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp index 578a3193..4f3ae4e7 100644 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -2,90 +2,144 @@ #include "StdAfx.h" -#include "../../../C/Alloc.h" - #include "../../Common/Defs.h" #include "FilterCoder.h" #include "StreamUtils.h" -static const UInt32 kBufferSize = 1 << 17; +/* + AES filters need 16-bytes alignment for HARDWARE-AES instructions. + So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block. + + AES-CBC filters need data size aligned for 16-bytes. + So the encoder can add zeros to the end of original stream. + + 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. +*/ + + +static const UInt32 kBufSize = 1 << 20; -CFilterCoder::CFilterCoder() +STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } +STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } + +HRESULT CFilterCoder::Alloc() { - _buffer = (Byte *)::MidAlloc(kBufferSize); - if (_buffer == 0) - throw 1; + UInt32 size = MyMin(_inBufSize, _outBufSize); + /* minimal bufSize is 16 bytes for AES and IA64 filter. + bufSize for AES must be aligned for 16 bytes. + We use (1 << 12) min size to support future aligned filters. */ + const UInt32 kMinSize = 1 << 12; + size &= ~(UInt32)(kMinSize - 1); + if (size < kMinSize) + size = kMinSize; + if (!_buf || _bufSize != size) + { + AllocAlignedMask(size, 16 - 1); + if (!_buf) + return E_OUTOFMEMORY; + _bufSize = size; + } + return S_OK; } -CFilterCoder::~CFilterCoder() +HRESULT CFilterCoder::Init_and_Alloc() { - ::MidFree(_buffer); + RINOK(Filter->Init()); + return Alloc(); } -HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) +CFilterCoder::CFilterCoder(bool encodeMode): + _bufSize(0), + _inBufSize(kBufSize), + _outBufSize(kBufSize), + _encodeMode(encodeMode), + _outSizeIsDefined(false), + _outSize(0), + _nowPos64(0) + {} + +CFilterCoder::~CFilterCoder() { - if (_outSizeIsDefined) - { - UInt64 remSize = _outSize - _nowPos64; - if (size > remSize) - size = (UInt32)remSize; - } - RINOK(WriteStream(outStream, _buffer, size)); - _nowPos64 += size; - return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - RINOK(Init()); - UInt32 bufferPos = 0; - _outSizeIsDefined = (outSize != 0); - if (_outSizeIsDefined) - _outSize = *outSize; + RINOK(Init_and_Alloc()); + + UInt64 nowPos64 = 0; + bool inputFinished = false; + UInt32 pos = 0; - while (!_outSizeIsDefined || _nowPos64 < _outSize) + while (!outSize || nowPos64 < *outSize) { - size_t processedSize = kBufferSize - bufferPos; - - // Change it: It can be optimized using ReadPart - RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); + UInt32 endPos = pos; - UInt32 endPos = bufferPos + (UInt32)processedSize; - - bufferPos = Filter->Filter(_buffer, endPos); - if (bufferPos > endPos) + if (!inputFinished) { - for (; endPos < bufferPos; endPos++) - _buffer[endPos] = 0; - bufferPos = Filter->Filter(_buffer, endPos); + size_t processedSize = _bufSize - pos; + RINOK(ReadStream(inStream, _buf + pos, &processedSize)); + endPos = pos + (UInt32)processedSize; + inputFinished = (endPos != _bufSize); } - if (bufferPos == 0) + pos = Filter->Filter(_buf, endPos); + + if (pos > endPos) { - if (endPos == 0) - return S_OK; - return WriteWithLimit(outStream, endPos); + // AES + if (!inputFinished || pos > _bufSize) + return E_FAIL; + if (!_encodeMode) + return S_FALSE; + + do + _buf[endPos] = 0; + while (++endPos != pos); + + if (pos != Filter->Filter(_buf, pos)) + return E_FAIL; } - RINOK(WriteWithLimit(outStream, bufferPos)); - if (progress != NULL) + + if (endPos == 0) + return S_OK; + + UInt32 size = (pos != 0 ? pos : endPos); + if (outSize) { - RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); + UInt64 remSize = *outSize - nowPos64; + if (size > remSize) + size = (UInt32)remSize; } + + RINOK(WriteStream(outStream, _buf, size)); + nowPos64 += size; + + if (pos == 0) + return S_OK; + + if (progress) + RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)); + UInt32 i = 0; - while (bufferPos < endPos) - _buffer[i++] = _buffer[bufferPos++]; - bufferPos = i; + while (pos < endPos) + _buf[i++] = _buf[pos++]; + pos = i; } + return S_OK; } + + +// ---------- Write to Filter ---------- + STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { - _bufferPos = 0; _outStream = outStream; - return Init(); + return S_OK; } STDMETHODIMP CFilterCoder::ReleaseOutStream() @@ -94,76 +148,154 @@ STDMETHODIMP CFilterCoder::ReleaseOutStream() return S_OK; } +HRESULT CFilterCoder::Flush2() +{ + while (_convSize != 0) + { + UInt32 num = _convSize; + if (_outSizeIsDefined) + { + UInt64 rem = _outSize - _nowPos64; + if (num > rem) + num = (UInt32)rem; + if (num == 0) + return k_My_HRESULT_WritingWasCut; + } + + UInt32 processed = 0; + 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); + } + + if (_convPos != 0) + { + UInt32 num = _bufPos - _convPos; + for (UInt32 i = 0; i < num; i++) + _buf[i] = _buf[_convPos + i]; + _bufPos = num; + _convPos = 0; + } + + return S_OK; +} STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; - while (size > 0) + + while (size != 0) { - UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos); - memcpy(_buffer + _bufferPos, data, sizeTemp); - size -= sizeTemp; - if (processedSize != NULL) - *processedSize += sizeTemp; - data = (const Byte *)data + sizeTemp; - UInt32 endPos = _bufferPos + sizeTemp; - _bufferPos = Filter->Filter(_buffer, endPos); - if (_bufferPos == 0) + RINOK(Flush2()); + + // _convSize is 0 + // _convPos is 0 + // _bufPos is small + + if (_bufPos != _bufSize) { - _bufferPos = endPos; - break; + UInt32 num = MyMin(size, _bufSize - _bufPos); + memcpy(_buf + _bufPos, data, num); + size -= num; + data = (const Byte *)data + num; + if (processedSize) + *processedSize += num; + _bufPos += num; + if (_bufPos != _bufSize) + continue; } - if (_bufferPos > endPos) - { - if (size != 0) - return E_FAIL; + + // _bufPos == _bufSize + _convSize = Filter->Filter(_buf, _bufPos); + + if (_convSize == 0) break; + if (_convSize > _bufPos) + { + // that case is not possible. + _convSize = 0; + return E_FAIL; } - RINOK(WriteWithLimit(_outStream, _bufferPos)); - UInt32 i = 0; - while (_bufferPos < endPos) - _buffer[i++] = _buffer[_bufferPos++]; - _bufferPos = i; } + return S_OK; } -STDMETHODIMP CFilterCoder::Flush() +STDMETHODIMP CFilterCoder::OutStreamFinish() { - if (_bufferPos != 0) + for (;;) { - // _buffer contains only data refused by previous Filter->Filter call. - UInt32 endPos = Filter->Filter(_buffer, _bufferPos); - if (endPos > _bufferPos) + RINOK(Flush2()); + if (_bufPos == 0) + break; + _convSize = Filter->Filter(_buf, _bufPos); + if (_convSize == 0) + _convSize = _bufPos; + else if (_convSize > _bufPos) { - for (; _bufferPos < endPos; _bufferPos++) - _buffer[_bufferPos] = 0; - if (Filter->Filter(_buffer, endPos) != endPos) + // AES + if (_convSize > _bufSize) + { + _convSize = 0; + return E_FAIL; + } + if (!_encodeMode) + { + _convSize = 0; + return S_FALSE; + } + for (; _bufPos < _convSize; _bufPos++) + _buf[_bufPos] = 0; + _convSize = Filter->Filter(_buf, _bufPos); + if (_convSize != _bufPos) return E_FAIL; } - RINOK(WriteWithLimit(_outStream, _bufferPos)); - _bufferPos = 0; } - CMyComPtr<IOutStreamFlush> flush; - _outStream.QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) - return flush->Flush(); + + CMyComPtr<IOutStreamFinish> finish; + _outStream.QueryInterface(IID_IOutStreamFinish, &finish); + if (finish) + return finish->OutStreamFinish(); return S_OK; } +// ---------- Init functions ---------- -void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream) +STDMETHODIMP CFilterCoder::InitEncoder() { - _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; - _inStream = inStream; - Init2(); + InitSpecVars(); + return Init_and_Alloc(); +} + +HRESULT CFilterCoder::Init_NoSubFilterInit() +{ + InitSpecVars(); + return Alloc(); +} + +STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize) +{ + InitSpecVars(); + if (outSize) + { + _outSize = *outSize; + _outSizeIsDefined = true; + } + return Init_and_Alloc(); } +// ---------- Read from Filter ---------- + STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { - SetInStream_NoSubFilterInit(inStream); - return Init(); + _inStream = inStream; + return S_OK; } STDMETHODIMP CFilterCoder::ReleaseInStream() @@ -172,94 +304,115 @@ STDMETHODIMP CFilterCoder::ReleaseInStream() return S_OK; } + STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; - while (size > 0) + + while (size != 0) { - if (_convertedPosBegin != _convertedPosEnd) + if (_convSize != 0) { - UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); - memcpy(data, _buffer + _convertedPosBegin, sizeTemp); - _convertedPosBegin += sizeTemp; - data = (void *)((Byte *)data + sizeTemp); - size -= sizeTemp; - if (processedSize != NULL) - *processedSize += sizeTemp; + if (size > _convSize) + size = _convSize; + if (_outSizeIsDefined) + { + UInt64 rem = _outSize - _nowPos64; + if (size > rem) + size = (UInt32)rem; + } + memcpy(data, _buf + _convPos, size); + _convPos += size; + _convSize -= size; + _nowPos64 += size; + if (processedSize) + *processedSize = size; break; } - UInt32 i; - for (i = 0; _convertedPosEnd + i < _bufferPos; i++) - _buffer[i] = _buffer[_convertedPosEnd + i]; - _bufferPos = i; - _convertedPosBegin = _convertedPosEnd = 0; - size_t processedSizeTemp = kBufferSize - _bufferPos; - RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); - _bufferPos += (UInt32)processedSizeTemp; - _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); - if (_convertedPosEnd == 0) + + if (_convPos != 0) + { + UInt32 num = _bufPos - _convPos; + for (UInt32 i = 0; i < num; i++) + _buf[i] = _buf[_convPos + i]; + _bufPos = num; + _convPos = 0; + } + + { + size_t readSize = _bufSize - _bufPos; + HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize); + _bufPos += (UInt32)readSize; + RINOK(res); + } + + _convSize = Filter->Filter(_buf, _bufPos); + + if (_convSize == 0) { - if (_bufferPos == 0) + if (_bufPos == 0) break; - _convertedPosEnd = _bufferPos; // check it + // BCJ + _convSize = _bufPos; continue; } - if (_convertedPosEnd > _bufferPos) + + if (_convSize > _bufPos) { - for (; _bufferPos < _convertedPosEnd; _bufferPos++) - _buffer[_bufferPos] = 0; - _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); + // AES + if (_convSize > _bufSize) + return E_FAIL; + if (!_encodeMode) + return S_FALSE; + + do + _buf[_bufPos] = 0; + while (++_bufPos != _convSize); + + _convSize = Filter->Filter(_buf, _convSize); + if (_convSize != _bufPos) + return E_FAIL; } } + return S_OK; } + #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) -{ - return _setPassword->CryptoSetPassword(data, size); -} + { return _SetPassword->CryptoSetPassword(data, size); } STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size) -{ - return _cryptoProperties->SetKey(data, size); -} + { return _CryptoProperties->SetKey(data, size); } STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size) -{ - return _cryptoProperties->SetInitVector(data, size); -} + { return _CryptoProperties->SetInitVector(data, size); } #endif + #ifndef EXTRACT_ONLY + STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, - const PROPVARIANT *properties, UInt32 numProperties) -{ - return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); -} + const PROPVARIANT *properties, UInt32 numProperties) + { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) -{ - return _writeCoderProperties->WriteCoderProperties(outStream); -} + { return _WriteCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() -{ - return _CryptoResetSalt->ResetSalt(); -} + { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() -{ - return _CryptoResetInitVector->ResetInitVector(); -} + { return _CryptoResetInitVector->ResetInitVector(); } + #endif + STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) -{ - return _setDecoderProperties->SetDecoderProperties2(data, size); -} + { return _SetDecoderProperties2->SetDecoderProperties2(data, size); } diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h index 2b8f142f..cde33c88 100644 --- a/CPP/7zip/Common/FilterCoder.h +++ b/CPP/7zip/Common/FilterCoder.h @@ -3,106 +3,204 @@ #ifndef __FILTER_CODER_H #define __FILTER_CODER_H +#include "../../../C/Alloc.h" + #include "../../Common/MyCom.h" #include "../ICoder.h" + +#ifndef _NO_CRYPTO #include "../IPassword.h" +#endif #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; } + +struct CAlignedMidBuffer +{ + #ifndef _WIN32 + + Byte *_buf; + + CAlignedMidBuffer(): _buf(NULL) {} + ~CAlignedMidBuffer() { ::MidFree(_buf); } + + void AllocAlignedMask(size_t size, size_t) + { + ::MidFree(_buf); + _buf = (Byte *)::MidAlloc(size); + } + + #else + + Byte *_bufBase; + Byte *_buf; + + CAlignedMidBuffer(): _bufBase(NULL), _buf(NULL) {} + ~CAlignedMidBuffer() { ::MidFree(_bufBase); } + + void AllocAlignedMask(size_t size, size_t alignMask) + { + ::MidFree(_bufBase); + _buf = NULL; + _bufBase = (Byte *)::MidAlloc(size + alignMask); + + if (_bufBase) + { + // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask); + _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask); + } + } + + #endif +}; + class CFilterCoder: public ICompressCoder, + + public ICompressSetOutStreamSize, + public ICompressInitEncoder, + public ICompressSetInStream, public ISequentialInStream, + public ICompressSetOutStream, public ISequentialOutStream, - public IOutStreamFlush, + public IOutStreamFinish, + + public ICompressSetBufSize, #ifndef _NO_CRYPTO public ICryptoSetPassword, public ICryptoProperties, #endif + #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif + public ICompressSetDecoderProperties2, - public CMyUnknownImp + public CMyUnknownImp, + public CAlignedMidBuffer { -protected: - Byte *_buffer; - CMyComPtr<ISequentialInStream> _inStream; - CMyComPtr<ISequentialOutStream> _outStream; - UInt32 _bufferPos; - UInt32 _convertedPosBegin; - UInt32 _convertedPosEnd; + UInt32 _bufSize; + UInt32 _inBufSize; + UInt32 _outBufSize; + + bool _encodeMode; bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; - void Init2() + CMyComPtr<ISequentialInStream> _inStream; + CMyComPtr<ISequentialOutStream> _outStream; + UInt32 _bufPos; + UInt32 _convPos; // current pos in buffer for converted data + UInt32 _convSize; // size of converted data starting from _convPos + + void InitSpecVars() { - _nowPos64 = 0; + _bufPos = 0; + _convPos = 0; + _convSize = 0; + _outSizeIsDefined = false; + _outSize = 0; + _nowPos64 = 0; } - HRESULT Init() - { - Init2(); - return Filter->Init(); - } + HRESULT Alloc(); + HRESULT Init_and_Alloc(); + HRESULT Flush2(); + + #ifndef _NO_CRYPTO + CMyComPtr<ICryptoSetPassword> _SetPassword; + CMyComPtr<ICryptoProperties> _CryptoProperties; + #endif - CMyComPtr<ICryptoSetPassword> _setPassword; - CMyComPtr<ICryptoProperties> _cryptoProperties; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; - CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; + CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif - CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; + + CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2; + public: CMyComPtr<ICompressFilter> Filter; - CFilterCoder(); + CFilterCoder(bool encodeMode); ~CFilterCoder(); - HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); -public: + class C_InStream_Releaser + { + public: + CFilterCoder *FilterCoder; + C_InStream_Releaser(): FilterCoder(NULL) {} + ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } + }; + + class C_OutStream_Releaser + { + public: + CFilterCoder *FilterCoder; + C_OutStream_Releaser(): FilterCoder(NULL) {} + ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } + }; + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + + 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(IOutStreamFlush) + 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) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword) + MY_QUERYINTERFACE_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(ICompressWriteCoderProperties, Filter, _WriteCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif - MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) + MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - STDMETHOD(ReleaseInStream)(); + + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(InitEncoder)(); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ + 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(Flush)(); + STDMETHOD(OutStreamFinish)(); + + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); @@ -110,6 +208,7 @@ public: STDMETHOD(SetKey)(const Byte *data, UInt32 size); STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); #endif + #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); @@ -117,26 +216,11 @@ public: // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); - void SetInStream_NoSubFilterInit(ISequentialInStream *inStream); - -}; - -class CInStreamReleaser -{ -public: - CFilterCoder *FilterCoder; - CInStreamReleaser(): FilterCoder(0) {} - ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } -}; - -class COutStreamReleaser -{ -public: - CFilterCoder *FilterCoder; - COutStreamReleaser(): FilterCoder(0) {} - ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } + + HRESULT Init_NoSubFilterInit(); }; #endif diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp index be65ba32..85d6a1aa 100644 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -13,7 +13,7 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static const UInt32 kTempBufSize = (1 << 20); +static const size_t kTempBufSize = (1 << 20); static CFSTR kTempFilePrefixString = FTEXT("7zt"); @@ -58,15 +58,19 @@ bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) bool CInOutTempBuffer::Write(const void *data, UInt32 size) { - if (_bufPos < kTempBufSize) + if (size == 0) + return true; + size_t cur = kTempBufSize - _bufPos; + if (cur != 0) { - UInt32 cur = MyMin(kTempBufSize - _bufPos, size); + if (cur > size) + cur = size; memcpy(_buf + _bufPos, data, cur); _crc = CrcUpdate(_crc, data, cur); _bufPos += cur; - size -= cur; - data = ((const Byte *)data) + cur; _size += cur; + size -= (UInt32)cur; + data = ((const Byte *)data) + cur; } return WriteToFile(data, size); } @@ -79,12 +83,13 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) UInt64 size = 0; UInt32 crc = CRC_INIT_VAL; - if (_bufPos > 0) + if (_bufPos != 0) { RINOK(WriteStream(stream, _buf, _bufPos)); crc = CrcUpdate(crc, _buf, _bufPos); size += _bufPos; } + if (_tempFileCreated) { NIO::CInFile inFile; @@ -102,18 +107,21 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) size += processed; } } + return (_crc == crc && size == _size) ? S_OK : E_FAIL; } +/* STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed) { if (!_buf->Write(data, size)) { - if (processed != NULL) + if (processed) *processed = 0; return E_FAIL; } - if (processed != NULL) + if (processed) *processed = size; return S_OK; } +*/ diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h index 256d7242..204a105f 100644 --- a/CPP/7zip/Common/InOutTempBuffer.h +++ b/CPP/7zip/Common/InOutTempBuffer.h @@ -13,10 +13,10 @@ class CInOutTempBuffer NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; Byte *_buf; - UInt32 _bufPos; - bool _tempFileCreated; + size_t _bufPos; UInt64 _size; UInt32 _crc; + bool _tempFileCreated; bool WriteToFile(const void *data, UInt32 size); public: @@ -31,6 +31,7 @@ public: UInt64 GetDataSize() const { return _size; } }; +/* class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp @@ -42,5 +43,6 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; +*/ #endif diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index de236040..2ea718e7 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -279,7 +279,10 @@ STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *proce if (newPos >= _cachePhyPos && offsetInCache <= _cacheSize && size <= _cacheSize - (size_t)offsetInCache) - memcpy(data, _cache + (size_t)offsetInCache, size); + { + if (size != 0) + memcpy(data, _cache + (size_t)offsetInCache, size); + } else { if (newPos != _physPos) diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp index f05601cb..ca39fb45 100644 --- a/CPP/7zip/Common/LockedStream.cpp +++ b/CPP/7zip/Common/LockedStream.cpp @@ -1,23 +1,3 @@ // LockedStream.cpp #include "StdAfx.h" - -#include "LockedStream.h" - -HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, - UInt32 *processedSize) -{ - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); - return _stream->Read(data, size, processedSize); -} - -STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize = 0; - HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); - _pos += realProcessedSize; - if (processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h index 486e4220..efebf197 100644 --- a/CPP/7zip/Common/LockedStream.h +++ b/CPP/7zip/Common/LockedStream.h @@ -1,38 +1,6 @@ // LockedStream.h -#ifndef __LOCKEDSTREAM_H -#define __LOCKEDSTREAM_H - -#include "../../Windows/Synchronization.h" -#include "../../Common/MyCom.h" -#include "../IStream.h" - -class CLockedInStream -{ - CMyComPtr<IInStream> _stream; - NWindows::NSynchronization::CCriticalSection _criticalSection; -public: - void Init(IInStream *stream) - { _stream = stream; } - HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); -}; - -class CLockedSequentialInStreamImp: - public ISequentialInStream, - public CMyUnknownImp -{ - CLockedInStream *_lockedInStream; - UInt64 _pos; -public: - void Init(CLockedInStream *lockedInStream, UInt64 startPos) - { - _lockedInStream = lockedInStream; - _pos = startPos; - } - - MY_UNKNOWN_IMP - - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); -}; +#ifndef __LOCKED_STREAM_H +#define __LOCKED_STREAM_H #endif diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index f1c34ada..7c1e9979 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -10,12 +10,12 @@ using namespace NWindows; bool StringToBool(const UString &s, bool &res) { - if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON")) + if (s.IsEmpty() || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) { res = true; return true; } - if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF")) + if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF")) { res = false; return true; @@ -137,11 +137,10 @@ static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue void CProps::AddProp32(PROPID propid, UInt32 level) { - CProp prop; + CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = (UInt32)level; - Props.Add(prop); } class CCoderProps @@ -331,7 +330,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value) int index = FindPropIdExact(name); if (index < 0) return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; + const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; prop.Id = index; @@ -401,7 +400,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const int index = FindPropIdExact(realName); if (index < 0) return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; + const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; prop.Id = index; @@ -422,12 +421,20 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) { - int splitPos = s.Find(':'); - MethodName = s; + MethodName.Empty(); + int splitPos = s.Find(L':'); + { + UString temp = s; + if (splitPos >= 0) + temp.DeleteFrom(splitPos); + if (!temp.IsAscii()) + return E_INVALIDARG; + MethodName.SetFromWStr_if_Ascii(temp); + } if (splitPos < 0) return S_OK; - MethodName.DeleteFrom(splitPos); - return ParseParamsFromString(s.Ptr(splitPos + 1)); + PropsString = s.Ptr(splitPos + 1); + return ParseParamsFromString(PropsString); } HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 18672bde..765e425d 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -40,13 +40,12 @@ struct CProps void AddProp32(PROPID propid, UInt32 level); - void AddPropString(PROPID propid, const wchar_t *s) + void AddProp_Ascii(PROPID propid, const char *s) { - CProp prop; + CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = s; - Props.Add(prop); } HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const; @@ -100,6 +99,14 @@ public: return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); } + bool Are_Lzma_Model_Props_Defined() const + { + if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; + if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true; + if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true; + return false; + } + UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const { fixedNumber = false; @@ -153,12 +160,12 @@ public: return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19)); } - void AddLevelProp(UInt32 level) + void AddProp_Level(UInt32 level) { AddProp32(NCoderPropID::kLevel, level); } - void AddNumThreadsProp(UInt32 numThreads) + void AddProp_NumThreads(UInt32 numThreads) { AddProp32(NCoderPropID::kNumThreads, numThreads); } @@ -170,12 +177,14 @@ public: class COneMethodInfo: public CMethodProps { public: - UString MethodName; + AString MethodName; + UString PropsString; void Clear() { CMethodProps::Clear(); MethodName.Empty(); + PropsString.Empty(); } bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp index bac45c1c..41385ccb 100644 --- a/CPP/7zip/Common/ProgressUtils.cpp +++ b/CPP/7zip/Common/ProgressUtils.cpp @@ -4,11 +4,13 @@ #include "ProgressUtils.h" -CLocalProgress::CLocalProgress() -{ - ProgressOffset = InSize = OutSize = 0; - SendRatio = SendProgress = true; -} +CLocalProgress::CLocalProgress(): + ProgressOffset(0), + InSize(0), + OutSize(0), + SendRatio(true), + SendProgress(true) + {} void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { @@ -20,19 +22,26 @@ void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - UInt64 inSizeNew = InSize, outSizeNew = OutSize; + UInt64 inSize2 = InSize; + UInt64 outSize2 = OutSize; + if (inSize) - inSizeNew += (*inSize); + inSize2 += (*inSize); if (outSize) - outSizeNew += (*outSize); + outSize2 += (*outSize); + if (SendRatio && _ratioProgress) { - RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); + RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2)); } - inSizeNew += ProgressOffset; - outSizeNew += ProgressOffset; + if (SendProgress) - return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); + { + inSize2 += ProgressOffset; + outSize2 += ProgressOffset; + return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2); + } + return S_OK; } diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h index bae5395c..e94265ba 100644 --- a/CPP/7zip/Common/ProgressUtils.h +++ b/CPP/7zip/Common/ProgressUtils.h @@ -1,7 +1,7 @@ // ProgressUtils.h -#ifndef __PROGRESSUTILS_H -#define __PROGRESSUTILS_H +#ifndef __PROGRESS_UTILS_H +#define __PROGRESS_UTILS_H #include "../../Common/MyCom.h" @@ -23,10 +23,11 @@ public: bool SendProgress; CLocalProgress(); + void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp index 10daef71..2ce6fd85 100644 --- a/CPP/7zip/Common/PropId.cpp +++ b/CPP/7zip/Common/PropId.cpp @@ -5,7 +5,7 @@ #include "../PropID.h" // VARTYPE -Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = +const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = { VT_EMPTY, VT_UI4, @@ -95,5 +95,11 @@ Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = VT_BOOL, VT_BOOL, VT_UI8, - VT_UI8 + VT_UI8, + VT_BSTR, // kpidNtReparse + VT_BSTR, + VT_UI8, + VT_UI8, + VT_BOOL, + VT_BSTR // kpidOutName }; diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h index edc3abdd..3421ba1b 100644 --- a/CPP/7zip/Common/RegisterArc.h +++ b/CPP/7zip/Common/RegisterArc.h @@ -7,18 +7,16 @@ struct CArcInfo { + UInt16 Flags; + Byte Id; + Byte SignatureSize; + UInt16 SignatureOffset; + + const Byte *Signature; const char *Name; const char *Ext; const char *AddExt; - Byte ClassId; - - Byte SignatureSize; - Byte Signature[20]; - UInt16 SignatureOffset; - - UInt16 Flags; - Func_CreateInArchive CreateInArchive; Func_CreateOutArchive CreateOutArchive; Func_IsArc IsArc; @@ -28,28 +26,53 @@ struct CArcInfo void RegisterArc(const CArcInfo *arcInfo) throw(); -#define REGISTER_ARC_NAME(x) CRegister ## x - -#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ - REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ - static REGISTER_ARC_NAME(x) g_RegisterArc; - -#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ - REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ - static REGISTER_ARC_NAME(x) g_RegisterArc; - #define IMP_CreateArcIn_2(c) \ static IInArchive *CreateArc() { return new c; } -#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler) +#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler()) #ifdef EXTRACT_ONLY #define IMP_CreateArcOut - #define REF_CreateArc_Pair CreateArc, NULL + #define CreateArcOut NULL #else - #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; } - #define REF_CreateArc_Pair CreateArc, CreateArcOut + #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); } #endif +#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \ + +#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \ + static CRegisterArc g_RegisterArc; + + +#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, CreateArc, NULL, isArc) + +#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \ + IMP_CreateArcIn_2(cls) \ + REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc) + +#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \ + REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc) + +#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \ + REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc) + + +#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn \ + IMP_CreateArcOut \ + REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) + +#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn \ + IMP_CreateArcOut \ + REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \ + struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \ + static CRegisterArcDecSig g_RegisterArc; + #endif diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h index 4222a305..7ddb7604 100644 --- a/CPP/7zip/Common/RegisterCodec.h +++ b/CPP/7zip/Common/RegisterCodec.h @@ -4,48 +4,103 @@ #define __REGISTER_CODEC_H #include "../Common/MethodId.h" + #include "../ICoder.h" typedef void * (*CreateCodecP)(); + struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; - const wchar_t *Name; - UInt32 NumInStreams; + const char *Name; + UInt32 NumStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo) throw(); + +#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); } +#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder) + #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x +#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo = #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; + #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x +#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++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; +#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \ + REGISTER_CODEC_VAR \ + { crDec, crEnc, id, name, 1, false }; \ + REGISTER_CODEC(x) + + +#ifdef EXTRACT_ONLY + #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ + REGISTER_CODEC_CREATE(CreateDec, clsDec) \ + REGISTER_CODEC_2(x, CreateDec, NULL, id, name) +#else + #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ + REGISTER_CODEC_CREATE(CreateDec, clsDec) \ + REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \ + REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name) +#endif + + + +#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter) + +#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \ + { crDec, crEnc, id, name, 1, true } + +#define REGISTER_FILTER(x, crDec, crEnc, id, name) \ + REGISTER_CODEC_VAR \ + REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \ + REGISTER_CODEC(x) + +#ifdef EXTRACT_ONLY + #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ + REGISTER_FILTER_CREATE(CreateDec, clsDec) \ + REGISTER_FILTER(x, CreateDec, NULL, id, name) +#else + #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ + REGISTER_FILTER_CREATE(CreateDec, clsDec) \ + REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \ + REGISTER_FILTER(x, CreateDec, CreateEnc, id, name) +#endif + + + struct CHasherInfo { IHasher * (*CreateHasher)(); CMethodId Id; - const wchar_t *Name; + const char *Name; UInt32 DigestSize; }; void RegisterHasher(const CHasherInfo *hasher) throw(); -#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x +#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x -#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \ - REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \ - static REGISTER_HASHER_NAME(x) g_RegisterHasher; +#define REGISTER_HASHER(cls, id, name, size) \ + STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { 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); }}; \ + static REGISTER_HASHER_NAME(cls) g_RegisterHasher; #endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp index 7a4c0ed2..435440c6 100644 --- a/CPP/7zip/Common/StreamBinder.cpp +++ b/CPP/7zip/Common/StreamBinder.cpp @@ -12,7 +12,7 @@ class CBinderInStream: { CStreamBinder *_binder; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); ~CBinderInStream() { _binder->CloseRead(); } CBinderInStream(CStreamBinder *binder): _binder(binder) {} @@ -27,7 +27,7 @@ class CBinderOutStream: { CStreamBinder *_binder; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); ~CBinderOutStream() { _binder->CloseWrite(); } CBinderOutStream(CStreamBinder *binder): _binder(binder) {} @@ -40,26 +40,38 @@ STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *proc WRes CStreamBinder::CreateEvents() { - RINOK(_canWrite_Event.Create(true)); + RINOK(_canWrite_Event.Create()); RINOK(_canRead_Event.Create()); return _readingWasClosed_Event.Create(); } void CStreamBinder::ReInit() { - _waitWrite = true; + _canWrite_Event.Reset(); _canRead_Event.Reset(); _readingWasClosed_Event.Reset(); + + // _readingWasClosed = false; + _readingWasClosed2 = false; + + _waitWrite = true; + _bufSize = 0; + _buf = NULL; ProcessedSize = 0; + // WritingWasCut = false; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { + // _readingWasClosed = false; + _readingWasClosed2 = false; + _waitWrite = true; _bufSize = 0; _buf = NULL; ProcessedSize = 0; + // WritingWasCut = false; CBinderInStream *inStreamSpec = new CBinderInStream(this); CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); @@ -108,19 +120,37 @@ HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSiz { if (processedSize) *processedSize = 0; - if (size != 0) + if (size == 0) + return S_OK; + + if (!_readingWasClosed2) { _buf = data; _bufSize = size; - _canWrite_Event.Reset(); _canRead_Event.Set(); + + /* + _canWrite_Event.Lock(); + if (_readingWasClosed) + _readingWasClosed2 = true; + */ HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); - if (waitResult != WAIT_OBJECT_0 + 0) - return S_FALSE; - if (processedSize) - *processedSize = size; + if (waitResult >= WAIT_OBJECT_0 + 2) + return E_FAIL; + + size -= _bufSize; + if (size != 0) + { + if (processedSize) + *processedSize = size; + return S_OK; + } + // if (waitResult == WAIT_OBJECT_0 + 1) + _readingWasClosed2 = true; } - return S_OK; + + // WritingWasCut = true; + return k_My_HRESULT_WritingWasCut; } diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h index f3fb5322..12088a94 100644 --- a/CPP/7zip/Common/StreamBinder.h +++ b/CPP/7zip/Common/StreamBinder.h @@ -7,11 +7,27 @@ #include "../IStream.h" +/* +We don't use probably UNSAFE version: +reader thread: + _canWrite_Event.Set(); + _readingWasClosed = true + _canWrite_Event.Set(); +writer thread: + _canWrite_Event.Wait() + if (_readingWasClosed) +Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set? +*/ + class CStreamBinder { - NWindows::NSynchronization::CManualResetEvent _canWrite_Event; + NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; NWindows::NSynchronization::CManualResetEvent _canRead_Event; NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event; + + // bool _readingWasClosed; + bool _readingWasClosed2; + // bool WritingWasCut; bool _waitWrite; UInt32 _bufSize; const void *_buf; @@ -20,13 +36,23 @@ public: WRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); + void ReInit(); + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); - void CloseRead() { _readingWasClosed_Event.Set(); } + + void CloseRead() + { + _readingWasClosed_Event.Set(); + // _readingWasClosed = true; + // _canWrite_Event.Set(); + } + void CloseWrite() { - // _bufSize must be = 0 + _buf = NULL; + _bufSize = 0; _canRead_Event.Set(); } }; diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp index 817017ab..8136716d 100644 --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -8,6 +8,41 @@ #include "StreamObjects.h" +STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= Buf.Size()) + return S_OK; + size_t rem = Buf.Size() - (size_t)_pos; + if (rem > size) + rem = (size_t)size; + memcpy(data, (const Byte *)Buf + (size_t)_pos, rem); + _pos += rem; + if (processedSize) + *processedSize = (UInt32)rem; + return S_OK; +} + +STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += Buf.Size(); break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; + if (newPosition) + *newPosition = offset; + return S_OK; +} + STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) @@ -43,25 +78,22 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi return S_OK; } -/* -void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream) +void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream) { + *stream = NULL; CBufInStream *inStreamSpec = new CBufInStream; CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec; - inStreamSpec->Init((const Byte *)data, size); + inStreamSpec->Init((const Byte *)data, size, ref); *stream = streamTemp.Detach(); } -*/ -void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream) +void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream) { - CReferenceBuf *referenceBuf = new CReferenceBuf; - CMyComPtr<IUnknown> ref = referenceBuf; - referenceBuf->Buf.CopyFrom((const Byte *)data, size); - - CBufInStream *inStreamSpec = new CBufInStream; + *stream = NULL; + CBufferInStream *inStreamSpec = new CBufferInStream; CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec; - inStreamSpec->Init(referenceBuf); + inStreamSpec->Buf.CopyFrom((const Byte *)data, size); + inStreamSpec->Init(); *stream = streamTemp.Detach(); } @@ -128,8 +160,11 @@ STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *p size_t rem = _size - _pos; if (rem > size) rem = (size_t)size; - memcpy(_buffer + _pos, data, rem); - _pos += rem; + if (rem != 0) + { + memcpy(_buffer + _pos, data, rem); + _pos += rem; + } if (processedSize) *processedSize = (UInt32)rem; return (rem != 0 || size == 0) ? S_OK : E_FAIL; diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h index d0c86b56..e20e9bd8 100644 --- a/CPP/7zip/Common/StreamObjects.h +++ b/CPP/7zip/Common/StreamObjects.h @@ -9,6 +9,21 @@ #include "../IStream.h" +class CBufferInStream: + public IInStream, + public CMyUnknownImp +{ + 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 @@ -40,8 +55,10 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; -// void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream); -void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream); +void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream); +void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream); +inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream) + { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); } class CByteDynBuffer { @@ -53,8 +70,8 @@ public: ~CByteDynBuffer() { Free(); } void Free() throw(); size_t GetCapacity() const { return _capacity; } - operator Byte*() const { return _buf; }; - operator const Byte*() const { return _buf; }; + operator Byte*() const { return _buf; } + operator const Byte*() const { return _buf; } bool EnsureCapacity(size_t capacity) throw(); }; diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp index 7fcc88f5..a2cacdde 100644 --- a/CPP/7zip/Common/UniqBlocks.cpp +++ b/CPP/7zip/Common/UniqBlocks.cpp @@ -4,13 +4,13 @@ #include "UniqBlocks.h" -int CUniqBlocks::AddUniq(const Byte *data, size_t size) +unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) { unsigned left = 0, right = Sorted.Size(); while (left != right) { unsigned mid = (left + right) / 2; - int index = Sorted[mid]; + unsigned index = Sorted[mid]; const CByteBuffer &buf = Bufs[index]; size_t sizeMid = buf.Size(); if (size < sizeMid) @@ -19,6 +19,8 @@ int CUniqBlocks::AddUniq(const Byte *data, size_t size) left = mid + 1; else { + if (size == 0) + return index; int cmp = memcmp(data, buf, size); if (cmp == 0) return index; @@ -28,10 +30,9 @@ int CUniqBlocks::AddUniq(const Byte *data, size_t size) left = mid + 1; } } - int index = Bufs.Size(); + unsigned index = Bufs.Size(); Sorted.Insert(left, index); - CByteBuffer &buf = Bufs.AddNew(); - buf.CopyFrom(data, size); + Bufs.AddNew().CopyFrom(data, size); return index; } @@ -47,10 +48,8 @@ void CUniqBlocks::GetReverseMap() { unsigned num = Sorted.Size(); BufIndexToSortedIndex.ClearAndSetSize(num); - int *p = &BufIndexToSortedIndex[0]; - unsigned i; - for (i = 0; i < num; i++) - p[i] = 0; - for (i = 0; i < num; i++) - p[Sorted[i]] = i; + unsigned *p = &BufIndexToSortedIndex[0]; + const unsigned *sorted = &Sorted[0]; + for (unsigned i = 0; i < num; i++) + p[sorted[i]] = i; } diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h index 9c08b09f..a376024e 100644 --- a/CPP/7zip/Common/UniqBlocks.h +++ b/CPP/7zip/Common/UniqBlocks.h @@ -10,20 +10,16 @@ struct CUniqBlocks { CObjectVector<CByteBuffer> Bufs; - CIntVector Sorted; - CIntVector BufIndexToSortedIndex; + CUIntVector Sorted; + CUIntVector BufIndexToSortedIndex; - int AddUniq(const Byte *data, size_t size); + unsigned AddUniq(const Byte *data, size_t size); UInt64 GetTotalSizeInBytes() const; void GetReverseMap(); bool IsOnlyEmpty() const { - if (Bufs.Size() == 0) - return true; - if (Bufs.Size() > 1) - return false; - return Bufs[0].Size() == 0; + return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0); } }; |