diff options
Diffstat (limited to 'CPP/7zip/Common/CreateCoder.cpp')
-rw-r--r-- | CPP/7zip/Common/CreateCoder.cpp | 316 |
1 files changed, 193 insertions, 123 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; |