xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/XzEncoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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 HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
19 }
20 
21 namespace NXz {
22 
InitCoderProps()23 void CEncoder::InitCoderProps()
24 {
25   XzProps_Init(&xzProps);
26 }
27 
CEncoder()28 CEncoder::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 
~CEncoder()37 CEncoder::~CEncoder()
38 {
39   if (_encoder)
40     XzEnc_Destroy(_encoder);
41 }
42 
43 
44 struct CMethodNamePair
45 {
46   UInt32 Id;
47   const char *Name;
48 };
49 
50 static 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 
FilterIdFromName(const wchar_t * name)62 static 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 
SetCheckSize(UInt32 checkSizeInBytes)74 HRESULT 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 
SetCoderProp(PROPID propID,const PROPVARIANT & prop)90 HRESULT 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 = (UInt32)(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 
Z7_COM7F_IMF(CEncoder::SetCoderProperties (const PROPID * propIDs,const PROPVARIANT * coderProps,UInt32 numProps))186 Z7_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 
Z7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt (const PROPID * propIDs,const PROPVARIANT * coderProps,UInt32 numProps))201 Z7_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 
Z7_COM7F_IMF(CEncoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 *,ICompressProgressInfo * progress))219 Z7_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