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