This commit is contained in:
Igor Pavlov
2015-06-15 00:00:00 +00:00
committed by Kornel Lesiński
parent 0713a3ab80
commit 54490d51d5
591 changed files with 34932 additions and 16390 deletions
+193 -123
View File
@@ -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;
+96 -41
View File
@@ -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
+20 -24
View File
@@ -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);
}
+48 -8
View File
@@ -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
}
+21 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
+16 -8
View File
@@ -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;
}
*/
+4 -2
View File
@@ -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
+4 -1
View File
@@ -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)
-20
View File
@@ -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;
}
+2 -34
View File
@@ -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
+17 -10
View File
@@ -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)
+15 -6
View File
@@ -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);
+21 -12
View File
@@ -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;
}
+4 -3
View File
@@ -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);
};
+8 -2
View File
@@ -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
};
+45 -22
View File
@@ -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
+62 -7
View File
@@ -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
+41 -11
View File
@@ -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;
}
+29 -3
View File
@@ -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();
}
};
+48 -13
View File
@@ -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;
+21 -4
View File
@@ -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();
};
+10 -11
View File
@@ -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;
}
+4 -8
View File
@@ -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);
}
};