1// Lzma2Encoder.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/Alloc.h"
6
7#include "../Common/CWrappers.h"
8#include "../Common/StreamUtils.h"
9
10#include "Lzma2Encoder.h"
11
12namespace NCompress {
13
14namespace NLzma {
15
16HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);
17
18}
19
20namespace NLzma2 {
21
22static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
23static void SzBigFree(void *, void *address) { BigFree(address); }
24static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
25
26static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
27static void SzFree(void *, void *address) { MyFree(address); }
28static ISzAlloc g_Alloc = { SzAlloc, SzFree };
29
30CEncoder::CEncoder()
31{
32  _encoder = 0;
33  _encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc);
34  if (_encoder == 0)
35    throw 1;
36}
37
38CEncoder::~CEncoder()
39{
40  if (_encoder != 0)
41    Lzma2Enc_Destroy(_encoder);
42}
43
44HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)
45{
46  switch (propID)
47  {
48    case NCoderPropID::kBlockSize:
49      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; break;
50    case NCoderPropID::kNumThreads:
51      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;
52    default:
53      RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps));
54  }
55  return S_OK;
56}
57
58STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
59    const PROPVARIANT *coderProps, UInt32 numProps)
60{
61  CLzma2EncProps lzma2Props;
62  Lzma2EncProps_Init(&lzma2Props);
63
64  for (UInt32 i = 0; i < numProps; i++)
65  {
66    RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props));
67  }
68  return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
69}
70
71STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
72{
73  Byte prop = Lzma2Enc_WriteProperties(_encoder);
74  return WriteStream(outStream, &prop, 1);
75}
76
77STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
78    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
79{
80  CSeqInStreamWrap inWrap(inStream);
81  CSeqOutStreamWrap outWrap(outStream);
82  CCompressProgressWrap progressWrap(progress);
83
84  SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL);
85  if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
86    return inWrap.Res;
87  if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
88    return outWrap.Res;
89  if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
90    return progressWrap.Res;
91  return SResToHRESULT(res);
92}
93
94}}
95