Source code

Revision control

Copy as Markdown

Other Tools

// XzEncoder.cpp↩
#include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "../../Common/MyString.h"
#include "../../Common/StringToInt.h"
#include "../Common/CWrappers.h"
#include "../Common/StreamUtils.h"
#include "XzEncoder.h"
namespace NCompress {↩
namespace NLzma2 {↩
HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);↩
}↩
namespace NXz {↩
void CEncoder::InitCoderProps()↩
{↩
XzProps_Init(&xzProps);↩
}↩
CEncoder::CEncoder()↩
{↩
XzProps_Init(&xzProps);↩
_encoder = NULL;↩
_encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc);↩
if (!_encoder)↩
throw 1;↩
}↩
CEncoder::~CEncoder()↩
{↩
if (_encoder)↩
XzEnc_Destroy(_encoder);↩
}↩
struct CMethodNamePair↩
{↩
UInt32 Id;↩
const char *Name;↩
};↩
static const CMethodNamePair g_NamePairs[] =↩
{↩
{ XZ_ID_Delta, "Delta" },↩
{ XZ_ID_X86, "BCJ" },↩
{ XZ_ID_PPC, "PPC" },↩
{ XZ_ID_IA64, "IA64" },↩
{ XZ_ID_ARM, "ARM" },↩
{ XZ_ID_ARMT, "ARMT" },↩
{ XZ_ID_SPARC, "SPARC" }↩
// { XZ_ID_LZMA2, "LZMA2" }↩
};↩
static int FilterIdFromName(const wchar_t *name)↩
{↩
for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)↩
{↩
const CMethodNamePair &pair = g_NamePairs[i];↩
if (StringsAreEqualNoCase_Ascii(name, pair.Name))↩
return (int)pair.Id;↩
}↩
return -1;↩
}↩
HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes)↩
{↩
unsigned id;↩
switch (checkSizeInBytes)↩
{↩
case 0: id = XZ_CHECK_NO; break;↩
case 4: id = XZ_CHECK_CRC32; break;↩
case 8: id = XZ_CHECK_CRC64; break;↩
case 32: id = XZ_CHECK_SHA256; break;↩
default: return E_INVALIDARG;↩
}↩
xzProps.checkId = id;↩
return S_OK;↩
}↩
HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)↩
{↩
if (propID == NCoderPropID::kNumThreads)↩
{↩
if (prop.vt != VT_UI4)↩
return E_INVALIDARG;↩
xzProps.numTotalThreads = (int)(prop.ulVal);↩
return S_OK;↩
}↩
if (propID == NCoderPropID::kCheckSize)↩
{↩
if (prop.vt != VT_UI4)↩
return E_INVALIDARG;↩
return SetCheckSize(prop.ulVal);↩
}↩
if (propID == NCoderPropID::kBlockSize2)↩
{↩
if (prop.vt == VT_UI4)↩
xzProps.blockSize = prop.ulVal;↩
else if (prop.vt == VT_UI8)↩
xzProps.blockSize = prop.uhVal.QuadPart;↩
else
return E_INVALIDARG;↩
return S_OK;↩
}↩
if (propID == NCoderPropID::kReduceSize)↩
{↩
if (prop.vt == VT_UI8)↩
xzProps.reduceSize = prop.uhVal.QuadPart;↩
else
return E_INVALIDARG;↩
return S_OK;↩
}↩
if (propID == NCoderPropID::kFilter)↩
{↩
if (prop.vt == VT_UI4)↩
{↩
UInt32 id32 = prop.ulVal;↩
if (id32 == XZ_ID_Delta)↩
return E_INVALIDARG;↩
xzProps.filterProps.id = prop.ulVal;↩
}↩
else
{↩
if (prop.vt != VT_BSTR)↩
return E_INVALIDARG;↩
const wchar_t *name = prop.bstrVal;↩
const wchar_t *end;↩
UInt32 id32 = ConvertStringToUInt32(name, &end);↩
if (end != name)↩
name = end;↩
else
{↩
if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta"))↩
{↩
name += 5; // strlen("Delta");↩
id32 = XZ_ID_Delta;↩
}↩
else
{↩
int filterId = FilterIdFromName(prop.bstrVal);↩
if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)↩
return E_INVALIDARG;↩
id32 = filterId;↩
}↩
}↩
if (id32 == XZ_ID_Delta)↩
{↩
wchar_t c = *name;↩
if (c != '-' && c != ':')↩
return E_INVALIDARG;↩
name++;↩
UInt32 delta = ConvertStringToUInt32(name, &end);↩
if (end == name || *end != 0 || delta == 0 || delta > 256)↩
return E_INVALIDARG;↩
xzProps.filterProps.delta = delta;↩
}↩
xzProps.filterProps.id = id32;↩
}↩
return S_OK;↩
}↩
return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props);↩
}↩
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,↩
const PROPVARIANT *coderProps, UInt32 numProps)↩
{↩
XzProps_Init(&xzProps);↩
for (UInt32 i = 0; i < numProps; i++)↩
{↩
RINOK(SetCoderProp(propIDs[i], coderProps[i]));↩
}↩
return S_OK;↩
// return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps));↩
}↩
STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,↩
const PROPVARIANT *coderProps, UInt32 numProps)↩
{↩
for (UInt32 i = 0; i < numProps; i++)↩
{↩
const PROPVARIANT &prop = coderProps[i];↩
PROPID propID = propIDs[i];↩
if (propID == NCoderPropID::kExpectedDataSize)↩
if (prop.vt == VT_UI8)↩
XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);↩
}↩
return S_OK;↩
}↩
#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \↩
if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;↩
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,↩
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)↩
{↩
CSeqInStreamWrap inWrap;↩
CSeqOutStreamWrap outWrap;↩
CCompressProgressWrap progressWrap;↩
inWrap.Init(inStream);↩
outWrap.Init(outStream);↩
progressWrap.Init(progress);↩
SRes res = XzEnc_SetProps(_encoder, &xzProps);↩
if (res == SZ_OK)↩
res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);↩
// SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL);↩
RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)↩
RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)↩
RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)↩
return SResToHRESULT(res);↩
}↩
}}↩