1// LzmaEncoder.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 "LzmaEncoder.h" 11 12namespace NCompress { 13namespace NLzma { 14 15CEncoder::CEncoder() 16{ 17 _encoder = NULL; 18 _encoder = LzmaEnc_Create(&g_Alloc); 19 if (!_encoder) 20 throw 1; 21} 22 23CEncoder::~CEncoder() 24{ 25 if (_encoder) 26 LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); 27} 28 29static inline wchar_t GetUpperChar(wchar_t c) 30{ 31 if (c >= 'a' && c <= 'z') 32 c -= 0x20; 33 return c; 34} 35 36static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) 37{ 38 wchar_t c = GetUpperChar(*s++); 39 if (c == L'H') 40 { 41 if (GetUpperChar(*s++) != L'C') 42 return 0; 43 int numHashBytesLoc = (int)(*s++ - L'0'); 44 if (numHashBytesLoc < 4 || numHashBytesLoc > 4) 45 return 0; 46 if (*s != 0) 47 return 0; 48 *btMode = 0; 49 *numHashBytes = numHashBytesLoc; 50 return 1; 51 } 52 53 if (c != L'B') 54 return 0; 55 if (GetUpperChar(*s++) != L'T') 56 return 0; 57 int numHashBytesLoc = (int)(*s++ - L'0'); 58 if (numHashBytesLoc < 2 || numHashBytesLoc > 4) 59 return 0; 60 if (*s != 0) 61 return 0; 62 *btMode = 1; 63 *numHashBytes = numHashBytesLoc; 64 return 1; 65} 66 67#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; 68 69HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) 70{ 71 if (propID == NCoderPropID::kMatchFinder) 72 { 73 if (prop.vt != VT_BSTR) 74 return E_INVALIDARG; 75 return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; 76 } 77 if (propID > NCoderPropID::kReduceSize) 78 return S_OK; 79 if (propID == NCoderPropID::kReduceSize) 80 { 81 if (prop.vt == VT_UI8) 82 ep.reduceSize = prop.uhVal.QuadPart; 83 return S_OK; 84 } 85 if (prop.vt != VT_UI4) 86 return E_INVALIDARG; 87 UInt32 v = prop.ulVal; 88 switch (propID) 89 { 90 case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break; 91 SET_PROP_32(kLevel, level) 92 SET_PROP_32(kNumFastBytes, fb) 93 SET_PROP_32(kMatchFinderCycles, mc) 94 SET_PROP_32(kAlgorithm, algo) 95 SET_PROP_32(kDictionarySize, dictSize) 96 SET_PROP_32(kPosStateBits, pb) 97 SET_PROP_32(kLitPosBits, lp) 98 SET_PROP_32(kLitContextBits, lc) 99 SET_PROP_32(kNumThreads, numThreads) 100 default: return E_INVALIDARG; 101 } 102 return S_OK; 103} 104 105STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, 106 const PROPVARIANT *coderProps, UInt32 numProps) 107{ 108 CLzmaEncProps props; 109 LzmaEncProps_Init(&props); 110 111 for (UInt32 i = 0; i < numProps; i++) 112 { 113 const PROPVARIANT &prop = coderProps[i]; 114 PROPID propID = propIDs[i]; 115 switch (propID) 116 { 117 case NCoderPropID::kEndMarker: 118 if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break; 119 default: 120 RINOK(SetLzmaProp(propID, prop, props)); 121 } 122 } 123 return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); 124} 125 126STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) 127{ 128 Byte props[LZMA_PROPS_SIZE]; 129 size_t size = LZMA_PROPS_SIZE; 130 RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); 131 return WriteStream(outStream, props, size); 132} 133 134STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 135 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) 136{ 137 CSeqInStreamWrap inWrap(inStream); 138 CSeqOutStreamWrap outWrap(outStream); 139 CCompressProgressWrap progressWrap(progress); 140 141 SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc); 142 _inputProcessed = inWrap.Processed; 143 if (res == SZ_ERROR_READ && inWrap.Res != S_OK) 144 return inWrap.Res; 145 if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) 146 return outWrap.Res; 147 if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK) 148 return progressWrap.Res; 149 return SResToHRESULT(res); 150} 151 152}} 153