1// XzEncoder.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/Alloc.h"
6
7#include "../../Common/MyString.h"
8#include "../../Common/StringToInt.h"
9
10#include "../Common/CWrappers.h"
11#include "../Common/StreamUtils.h"
12
13#include "XzEncoder.h"
14
15namespace NCompress {
16
17namespace NLzma2 {
18HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
19}
20
21namespace NXz {
22
23void CEncoder::InitCoderProps()
24{
25  XzProps_Init(&xzProps);
26}
27
28CEncoder::CEncoder()
29{
30  XzProps_Init(&xzProps);
31  _encoder = NULL;
32  _encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc);
33  if (!_encoder)
34    throw 1;
35}
36
37CEncoder::~CEncoder()
38{
39  if (_encoder)
40    XzEnc_Destroy(_encoder);
41}
42
43
44struct CMethodNamePair
45{
46  UInt32 Id;
47  const char *Name;
48};
49
50static const CMethodNamePair g_NamePairs[] =
51{
52  { XZ_ID_Delta, "Delta" },
53  { XZ_ID_X86, "BCJ" },
54  { XZ_ID_PPC, "PPC" },
55  { XZ_ID_IA64, "IA64" },
56  { XZ_ID_ARM, "ARM" },
57  { XZ_ID_ARMT, "ARMT" },
58  { XZ_ID_SPARC, "SPARC" }
59  // { XZ_ID_LZMA2, "LZMA2" }
60};
61
62static int FilterIdFromName(const wchar_t *name)
63{
64  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++)
65  {
66    const CMethodNamePair &pair = g_NamePairs[i];
67    if (StringsAreEqualNoCase_Ascii(name, pair.Name))
68      return (int)pair.Id;
69  }
70  return -1;
71}
72
73
74HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes)
75{
76  unsigned id;
77  switch (checkSizeInBytes)
78  {
79    case  0: id = XZ_CHECK_NO; break;
80    case  4: id = XZ_CHECK_CRC32; break;
81    case  8: id = XZ_CHECK_CRC64; break;
82    case 32: id = XZ_CHECK_SHA256; break;
83    default: return E_INVALIDARG;
84  }
85  xzProps.checkId = id;
86  return S_OK;
87}
88
89
90HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)
91{
92  if (propID == NCoderPropID::kNumThreads)
93  {
94    if (prop.vt != VT_UI4)
95      return E_INVALIDARG;
96    xzProps.numTotalThreads = (int)(prop.ulVal);
97    return S_OK;
98  }
99
100  if (propID == NCoderPropID::kCheckSize)
101  {
102    if (prop.vt != VT_UI4)
103      return E_INVALIDARG;
104    return SetCheckSize(prop.ulVal);
105  }
106
107  if (propID == NCoderPropID::kBlockSize2)
108  {
109    if (prop.vt == VT_UI4)
110      xzProps.blockSize = prop.ulVal;
111    else if (prop.vt == VT_UI8)
112      xzProps.blockSize = prop.uhVal.QuadPart;
113    else
114      return E_INVALIDARG;
115    return S_OK;
116  }
117
118  if (propID == NCoderPropID::kReduceSize)
119  {
120    if (prop.vt == VT_UI8)
121      xzProps.reduceSize = prop.uhVal.QuadPart;
122    else
123      return E_INVALIDARG;
124    return S_OK;
125  }
126
127  if (propID == NCoderPropID::kFilter)
128  {
129    if (prop.vt == VT_UI4)
130    {
131      const UInt32 id32 = prop.ulVal;
132      if (id32 == XZ_ID_Delta)
133        return E_INVALIDARG;
134      xzProps.filterProps.id = prop.ulVal;
135    }
136    else
137    {
138      if (prop.vt != VT_BSTR)
139        return E_INVALIDARG;
140
141      const wchar_t *name = prop.bstrVal;
142      const wchar_t *end;
143
144      UInt32 id32 = ConvertStringToUInt32(name, &end);
145
146      if (end != name)
147        name = end;
148      else
149      {
150        if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta"))
151        {
152          name += 5; // strlen("Delta");
153          id32 = XZ_ID_Delta;
154        }
155        else
156        {
157          const int filterId = FilterIdFromName(prop.bstrVal);
158          if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)
159            return E_INVALIDARG;
160          id32 = (unsigned)filterId;
161        }
162      }
163
164      if (id32 == XZ_ID_Delta)
165      {
166        const wchar_t c = *name;
167        if (c != '-' && c != ':')
168          return E_INVALIDARG;
169        name++;
170        const UInt32 delta = ConvertStringToUInt32(name, &end);
171        if (end == name || *end != 0 || delta == 0 || delta > 256)
172          return E_INVALIDARG;
173        xzProps.filterProps.delta = delta;
174      }
175
176      xzProps.filterProps.id = id32;
177    }
178
179    return S_OK;
180  }
181
182  return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props);
183}
184
185
186Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs,
187    const PROPVARIANT *coderProps, UInt32 numProps))
188{
189  XzProps_Init(&xzProps);
190
191  for (UInt32 i = 0; i < numProps; i++)
192  {
193    RINOK(SetCoderProp(propIDs[i], coderProps[i]))
194  }
195
196  return S_OK;
197  // return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps));
198}
199
200
201Z7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
202    const PROPVARIANT *coderProps, UInt32 numProps))
203{
204  for (UInt32 i = 0; i < numProps; i++)
205  {
206    const PROPVARIANT &prop = coderProps[i];
207    const PROPID propID = propIDs[i];
208    if (propID == NCoderPropID::kExpectedDataSize)
209      if (prop.vt == VT_UI8)
210        XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
211  }
212  return S_OK;
213}
214
215
216#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
217  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
218
219Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
220    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))
221{
222  CSeqInStreamWrap inWrap;
223  CSeqOutStreamWrap outWrap;
224  CCompressProgressWrap progressWrap;
225
226  inWrap.Init(inStream);
227  outWrap.Init(outStream);
228  progressWrap.Init(progress);
229
230  SRes res = XzEnc_SetProps(_encoder, &xzProps);
231  if (res == SZ_OK)
232    res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);
233
234  // SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL);
235
236  RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
237  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
238  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
239
240  return SResToHRESULT(res);
241}
242
243}}
244