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/Archive/XzHandler.cpp')
-rwxr-xr-xCPP/7zip/Archive/XzHandler.cpp115
1 files changed, 94 insertions, 21 deletions
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 64b7a586..8383488b 100755
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -8,6 +8,7 @@
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
+#include "../../Common/StringConvert.h"
#include "../ICoder.h"
@@ -40,13 +41,15 @@ namespace NXz {
struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
+static const wchar_t *k_LZMA2_Name = L"LZMA2";
+
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
#ifndef EXTRACT_ONLY
public IOutArchive,
public ISetProperties,
- public COutHandler,
+ public CMultiMethodProps,
#endif
public CMyUnknownImp
{
@@ -62,12 +65,12 @@ class CHandler:
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
- UInt32 _crcSize;
+ UInt32 _filterId;
void Init()
{
- _crcSize = 4;
- COutHandler::Init();
+ _filterId = 0;
+ CMultiMethodProps::Init();
}
HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
@@ -98,14 +101,14 @@ CHandler::CHandler()
Init();
}
-STATPROPSTG kProps[] =
+static STATPROPSTG const kProps[] =
{
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMethod, VT_BSTR}
};
-STATPROPSTG kArcProps[] =
+static STATPROPSTG const kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidNumBlocks, VT_UI4}
@@ -160,11 +163,11 @@ struct CMethodNamePair
const char *Name;
};
-static CMethodNamePair g_NamePairs[] =
+static const CMethodNamePair g_NamePairs[] =
{
{ XZ_ID_Subblock, "SB" },
{ XZ_ID_Delta, "Delta" },
- { XZ_ID_X86, "x86" },
+ { XZ_ID_X86, "BCJ" },
{ XZ_ID_PPC, "PPC" },
{ XZ_ID_IA64, "IA64" },
{ XZ_ID_ARM, "ARM" },
@@ -439,7 +442,10 @@ struct CXzUnpackerCPP
Byte *InBuf;
Byte *OutBuf;
CXzUnpacker p;
- CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}
+ CXzUnpackerCPP(): InBuf(0), OutBuf(0)
+ {
+ XzUnpacker_Construct(&p, &g_Alloc);
+ }
~CXzUnpackerCPP()
{
XzUnpacker_Free(&p);
@@ -483,7 +489,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CCompressProgressWrap progressWrap(progress);
- SRes res;
+ SRes res = S_OK;
const UInt32 kInBufSize = 1 << 15;
const UInt32 kOutBufSize = 1 << 21;
@@ -492,8 +498,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 inSize = 0;
UInt32 outPos = 0;
CXzUnpackerCPP xzu;
- res = XzUnpacker_Create(&xzu.p, &g_Alloc);
- if (res == SZ_OK)
+ XzUnpacker_Init(&xzu.p);
{
xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
@@ -534,6 +539,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
outPos = 0;
}
+ RINOK(lps->SetCur());
if (finished)
{
_packSize = lps->InSize;
@@ -553,7 +559,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
break;
}
- RINOK(lps->SetCur());
}
Int32 opRes;
@@ -573,8 +578,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return SResToHRESULT(res);
}
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(opRes));
- return S_OK;
+ return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
@@ -619,8 +623,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (IntToBool(newData))
{
+ UInt64 size;
{
- UInt64 size;
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
@@ -632,22 +636,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CLzma2EncProps lzma2Props;
Lzma2EncProps_Init(&lzma2Props);
- lzma2Props.lzmaProps.level = _level;
+ lzma2Props.lzmaProps.level = GetLevel();
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(0, &fileInStream));
CSeqInStreamWrap seqInStream(fileInStream);
+ {
+ NCOM::CPropVariant prop = (UInt64)size;
+ RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
+ }
+
for (int i = 0; i < _methods.Size(); i++)
{
COneMethodInfo &m = _methods[i];
- SetCompressionMethod2(m
+ SetGlobalLevelAndThreads(m
#ifndef _7ZIP_ST
, _numThreads
#endif
);
- if (m.IsLzma())
{
for (int j = 0; j < m.Props.Size(); j++)
{
@@ -666,7 +674,40 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
lps->Init(updateCallback, true);
CCompressProgressWrap progressWrap(progress);
- SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);
+ CXzProps xzProps;
+ CXzFilterProps filter;
+ XzProps_Init(&xzProps);
+ XzFilterProps_Init(&filter);
+ xzProps.lzma2Props = &lzma2Props;
+ xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
+ switch (_crcSize)
+ {
+ case 0: xzProps.checkId = XZ_CHECK_NO; break;
+ case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
+ case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
+ case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
+ default: return E_INVALIDARG;
+ }
+ filter.id = _filterId;
+ if (_filterId == XZ_ID_Delta)
+ {
+ bool deltaDefined = false;
+ for (int j = 0; j < _filterMethod.Props.Size(); j++)
+ {
+ const CProp &prop = _filterMethod.Props[j];
+ if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
+ {
+ UInt32 delta = (UInt32)prop.Value.ulVal;
+ if (delta < 1 || delta > 256)
+ return E_INVALIDARG;
+ filter.delta = delta;
+ deltaDefined = true;
+ }
+ }
+ if (!deltaDefined)
+ return E_INVALIDARG;
+ }
+ SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p);
if (res == SZ_OK)
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
return SResToHRESULT(res);
@@ -678,14 +719,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return NCompress::CopyStream(_stream, outStream, 0);
}
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
COM_TRY_BEGIN
- BeforeSetProperty();
+ Init();
for (int i = 0; i < numProps; i++)
{
RINOK(SetProperty(names[i], values[i]));
}
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ int k;
+ for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++)
+ {
+ const CMethodNamePair &pair = g_NamePairs[k];
+ UString m = GetUnicodeString(pair.Name);
+ if (_filterMethod.MethodName.CompareNoCase(m) == 0)
+ {
+ _filterId = pair.Id;
+ break;
+ }
+ }
+ if (k == ARRAY_SIZE(g_NamePairs))
+ return E_INVALIDARG;
+ }
+
+ int numEmptyMethods = GetNumEmptyMethods();
+ _methods.Delete(0, numEmptyMethods);
+ if (_methods.Size() > 1)
+ return E_INVALIDARG;
+ if (_methods.Size() == 1)
+ {
+ UString &methodName = _methods[0].MethodName;
+ if (methodName.IsEmpty())
+ methodName = k_LZMA2_Name;
+ else if (methodName.CompareNoCase(k_LZMA2_Name) != 0)
+ return E_INVALIDARG;
+ }
return S_OK;
COM_TRY_END
}