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
22CEncoder::CEncoder()
23{
24  _encoder = NULL;
25  _encoder = Lzma2Enc_Create(&g_AlignedAlloc, &g_BigAlloc);
26  if (!_encoder)
27    throw 1;
28}
29
30CEncoder::~CEncoder()
31{
32  if (_encoder)
33    Lzma2Enc_Destroy(_encoder);
34}
35
36
37HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
38HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)
39{
40  switch (propID)
41  {
42    case NCoderPropID::kBlockSize:
43    {
44      if (prop.vt == VT_UI4)
45        lzma2Props.blockSize = prop.ulVal;
46      else if (prop.vt == VT_UI8)
47        lzma2Props.blockSize = prop.uhVal.QuadPart;
48      else
49        return E_INVALIDARG;
50      break;
51    }
52    case NCoderPropID::kNumThreads:
53      if (prop.vt != VT_UI4)
54        return E_INVALIDARG;
55      lzma2Props.numTotalThreads = (int)(prop.ulVal);
56      break;
57    default:
58      RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps))
59  }
60  return S_OK;
61}
62
63
64Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs,
65    const PROPVARIANT *coderProps, UInt32 numProps))
66{
67  CLzma2EncProps lzma2Props;
68  Lzma2EncProps_Init(&lzma2Props);
69
70  for (UInt32 i = 0; i < numProps; i++)
71  {
72    RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props))
73  }
74  return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
75}
76
77
78Z7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
79    const PROPVARIANT *coderProps, UInt32 numProps))
80{
81  for (UInt32 i = 0; i < numProps; i++)
82  {
83    const PROPVARIANT &prop = coderProps[i];
84    const PROPID propID = propIDs[i];
85    if (propID == NCoderPropID::kExpectedDataSize)
86      if (prop.vt == VT_UI8)
87        Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart);
88  }
89  return S_OK;
90}
91
92
93Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))
94{
95  const Byte prop = Lzma2Enc_WriteProperties(_encoder);
96  return WriteStream(outStream, &prop, 1);
97}
98
99
100#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
101  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
102
103Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
104    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))
105{
106  CSeqInStreamWrap inWrap;
107  CSeqOutStreamWrap outWrap;
108  CCompressProgressWrap progressWrap;
109
110  inWrap.Init(inStream);
111  outWrap.Init(outStream);
112  progressWrap.Init(progress);
113
114  SRes res = Lzma2Enc_Encode2(_encoder,
115      &outWrap.vt, NULL, NULL,
116      &inWrap.vt, NULL, 0,
117      progress ? &progressWrap.vt : NULL);
118
119  RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
120  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
121  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
122
123  return SResToHRESULT(res);
124}
125
126}}
127