Welcome to mirror list, hosted at ThFree Co, Russian Federation.

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