XzEncoder.cpp (5772B)
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 25 void CEncoder::InitCoderProps() 26 { 27 XzProps_Init(&xzProps); 28 } 29 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 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 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 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 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 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 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 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 }}