mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-01-31 06:24:13 -06:00
15.05
This commit is contained in:
committed by
Kornel Lesiński
parent
0713a3ab80
commit
54490d51d5
+193
-123
@@ -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())
|
||||
if (codec.NumStreams == 1)
|
||||
{
|
||||
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));
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
bool FindMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, UString &name);
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
CMethodId &methodId, UInt32 &numStreams);
|
||||
|
||||
bool FindMethod(
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
+296
-143
@@ -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.
|
||||
|
||||
CFilterCoder::CFilterCoder()
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::Init_and_Alloc()
|
||||
{
|
||||
RINOK(Filter->Init());
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
CFilterCoder::CFilterCoder(bool encodeMode):
|
||||
_bufSize(0),
|
||||
_inBufSize(kBufSize),
|
||||
_outBufSize(kBufSize),
|
||||
_encodeMode(encodeMode),
|
||||
_outSizeIsDefined(false),
|
||||
_outSize(0),
|
||||
_nowPos64(0)
|
||||
{}
|
||||
|
||||
CFilterCoder::~CFilterCoder()
|
||||
{
|
||||
::MidFree(_buffer);
|
||||
}
|
||||
|
||||
HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
|
||||
{
|
||||
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;
|
||||
UInt32 endPos = pos;
|
||||
|
||||
// Change it: It can be optimized using ReadPart
|
||||
RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));
|
||||
|
||||
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)
|
||||
|
||||
// _bufPos == _bufSize
|
||||
_convSize = Filter->Filter(_buf, _bufPos);
|
||||
|
||||
if (_convSize == 0)
|
||||
break;
|
||||
if (_convSize > _bufPos)
|
||||
{
|
||||
if (size != 0)
|
||||
return E_FAIL;
|
||||
break;
|
||||
// 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)
|
||||
{
|
||||
if (_bufferPos == 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 (_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); }
|
||||
|
||||
+133
-49
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user