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 15namespace NCompress { 16 17namespace NLzma2 { 18HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); 19} 20 21namespace NXz { 22 23void CEncoder::InitCoderProps() 24{ 25 XzProps_Init(&xzProps); 26} 27 28CEncoder::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 37CEncoder::~CEncoder() 38{ 39 if (_encoder) 40 XzEnc_Destroy(_encoder); 41} 42 43 44struct CMethodNamePair 45{ 46 UInt32 Id; 47 const char *Name; 48}; 49 50static 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 62static 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 74HRESULT 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 90HRESULT 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 = (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 186Z7_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 201Z7_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 219Z7_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