5 #include "../../../C/Alloc.h"
\r
7 #include "../Common/CWrappers.h"
\r
8 #include "../Common/StreamUtils.h"
\r
10 #include "LzmaEncoder.h"
\r
12 namespace NCompress {
\r
15 static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
\r
16 static void SzBigFree(void *, void *address) { BigFree(address); }
\r
17 static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
\r
19 static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
\r
20 static void SzFree(void *, void *address) { MyFree(address); }
\r
21 static ISzAlloc g_Alloc = { SzAlloc, SzFree };
\r
23 CEncoder::CEncoder()
\r
26 _encoder = LzmaEnc_Create(&g_Alloc);
\r
31 CEncoder::~CEncoder()
\r
34 LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);
\r
37 inline wchar_t GetUpperChar(wchar_t c)
\r
39 if (c >= 'a' && c <= 'z')
\r
44 static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
\r
46 wchar_t c = GetUpperChar(*s++);
\r
49 if (GetUpperChar(*s++) != L'C')
\r
51 int numHashBytesLoc = (int)(*s++ - L'0');
\r
52 if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
\r
57 *numHashBytes = numHashBytesLoc;
\r
63 if (GetUpperChar(*s++) != L'T')
\r
65 int numHashBytesLoc = (int)(*s++ - L'0');
\r
66 if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
\r
68 c = GetUpperChar(*s++);
\r
72 *numHashBytes = numHashBytesLoc;
\r
76 HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
\r
78 if (propID == NCoderPropID::kMatchFinder)
\r
80 if (prop.vt != VT_BSTR)
\r
81 return E_INVALIDARG;
\r
82 return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
\r
84 if (prop.vt != VT_UI4)
\r
85 return E_INVALIDARG;
\r
86 UInt32 v = prop.ulVal;
\r
89 case NCoderPropID::kNumFastBytes: ep.fb = v; break;
\r
90 case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;
\r
91 case NCoderPropID::kAlgorithm: ep.algo = v; break;
\r
92 case NCoderPropID::kDictionarySize: ep.dictSize = v; break;
\r
93 case NCoderPropID::kPosStateBits: ep.pb = v; break;
\r
94 case NCoderPropID::kLitPosBits: ep.lp = v; break;
\r
95 case NCoderPropID::kLitContextBits: ep.lc = v; break;
\r
96 default: return E_INVALIDARG;
\r
101 STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
\r
102 const PROPVARIANT *coderProps, UInt32 numProps)
\r
104 CLzmaEncProps props;
\r
105 LzmaEncProps_Init(&props);
\r
107 for (UInt32 i = 0; i < numProps; i++)
\r
109 const PROPVARIANT &prop = coderProps[i];
\r
110 PROPID propID = propIDs[i];
\r
113 case NCoderPropID::kEndMarker:
\r
114 if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;
\r
115 case NCoderPropID::kNumThreads:
\r
116 if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;
\r
118 RINOK(SetLzmaProp(propID, prop, props));
\r
121 return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));
\r
124 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
\r
126 Byte props[LZMA_PROPS_SIZE];
\r
127 size_t size = LZMA_PROPS_SIZE;
\r
128 RINOK(LzmaEnc_WriteProperties(_encoder, props, &size));
\r
129 return WriteStream(outStream, props, size);
\r
132 STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
\r
133 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
\r
135 CSeqInStreamWrap inWrap(inStream);
\r
136 CSeqOutStreamWrap outWrap(outStream);
\r
137 CCompressProgressWrap progressWrap(progress);
\r
139 SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);
\r
140 if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
\r
142 if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
\r
143 return outWrap.Res;
\r
144 if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
\r
145 return progressWrap.Res;
\r
146 return SResToHRESULT(res);
\r