OLD | NEW |
| (Empty) |
1 // LzmaEncoder.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 extern "C" | |
6 { | |
7 #include "../../../C/Alloc.h" | |
8 } | |
9 | |
10 #include "../Common/StreamUtils.h" | |
11 | |
12 #include "LzmaEncoder.h" | |
13 | |
14 static HRESULT SResToHRESULT(SRes res) | |
15 { | |
16 switch(res) | |
17 { | |
18 case SZ_OK: return S_OK; | |
19 case SZ_ERROR_MEM: return E_OUTOFMEMORY; | |
20 case SZ_ERROR_PARAM: return E_INVALIDARG; | |
21 // case SZ_ERROR_THREAD: return E_FAIL; | |
22 } | |
23 return E_FAIL; | |
24 } | |
25 | |
26 namespace NCompress { | |
27 namespace NLzma { | |
28 | |
29 static const UInt32 kStreamStepSize = (UInt32)1 << 31; | |
30 | |
31 static SRes MyRead(void *object, void *data, size_t *size) | |
32 { | |
33 UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize)
; | |
34 HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSi
ze); | |
35 *size = curSize; | |
36 return (SRes)res; | |
37 } | |
38 | |
39 static size_t MyWrite(void *object, const void *data, size_t size) | |
40 { | |
41 CSeqOutStream *p = (CSeqOutStream *)object; | |
42 p->Res = WriteStream(p->RealStream, data, size); | |
43 if (p->Res != 0) | |
44 return 0; | |
45 return size; | |
46 } | |
47 | |
48 static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } | |
49 static void SzBigFree(void *, void *address) { BigFree(address); } | |
50 static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; | |
51 | |
52 static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } | |
53 static void SzFree(void *, void *address) { MyFree(address); } | |
54 static ISzAlloc g_Alloc = { SzAlloc, SzFree }; | |
55 | |
56 CEncoder::CEncoder() | |
57 { | |
58 _seqInStream.SeqInStream.Read = MyRead; | |
59 _seqOutStream.SeqOutStream.Write = MyWrite; | |
60 _encoder = 0; | |
61 _encoder = LzmaEnc_Create(&g_Alloc); | |
62 if (_encoder == 0) | |
63 throw 1; | |
64 } | |
65 | |
66 CEncoder::~CEncoder() | |
67 { | |
68 if (_encoder != 0) | |
69 LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); | |
70 } | |
71 | |
72 inline wchar_t GetUpperChar(wchar_t c) | |
73 { | |
74 if (c >= 'a' && c <= 'z') | |
75 c -= 0x20; | |
76 return c; | |
77 } | |
78 | |
79 static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) | |
80 { | |
81 wchar_t c = GetUpperChar(*s++); | |
82 if (c == L'H') | |
83 { | |
84 if (GetUpperChar(*s++) != L'C') | |
85 return 0; | |
86 int numHashBytesLoc = (int)(*s++ - L'0'); | |
87 if (numHashBytesLoc < 4 || numHashBytesLoc > 4) | |
88 return 0; | |
89 if (*s++ != 0) | |
90 return 0; | |
91 *btMode = 0; | |
92 *numHashBytes = numHashBytesLoc; | |
93 return 1; | |
94 } | |
95 if (c != L'B') | |
96 return 0; | |
97 | |
98 if (GetUpperChar(*s++) != L'T') | |
99 return 0; | |
100 int numHashBytesLoc = (int)(*s++ - L'0'); | |
101 if (numHashBytesLoc < 2 || numHashBytesLoc > 4) | |
102 return 0; | |
103 c = GetUpperChar(*s++); | |
104 if (c != L'\0') | |
105 return 0; | |
106 *btMode = 1; | |
107 *numHashBytes = numHashBytesLoc; | |
108 return 1; | |
109 } | |
110 | |
111 STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, | |
112 const PROPVARIANT *coderProps, UInt32 numProps) | |
113 { | |
114 CLzmaEncProps props; | |
115 LzmaEncProps_Init(&props); | |
116 | |
117 for (UInt32 i = 0; i < numProps; i++) | |
118 { | |
119 const PROPVARIANT &prop = coderProps[i]; | |
120 switch (propIDs[i]) | |
121 { | |
122 case NCoderPropID::kNumFastBytes: | |
123 if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break
; | |
124 case NCoderPropID::kMatchFinderCycles: | |
125 if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break
; | |
126 case NCoderPropID::kAlgorithm: | |
127 if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; bre
ak; | |
128 case NCoderPropID::kDictionarySize: | |
129 if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal;
break; | |
130 case NCoderPropID::kPosStateBits: | |
131 if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break
; | |
132 case NCoderPropID::kLitPosBits: | |
133 if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break
; | |
134 case NCoderPropID::kLitContextBits: | |
135 if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break
; | |
136 case NCoderPropID::kNumThreads: | |
137 if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVa
l; break; | |
138 case NCoderPropID::kMultiThread: | |
139 if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.b
oolVal == VARIANT_TRUE) ? 2 : 1); break; | |
140 case NCoderPropID::kEndMarker: | |
141 if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.
boolVal == VARIANT_TRUE); break; | |
142 case NCoderPropID::kMatchFinder: | |
143 if (prop.vt != VT_BSTR) return E_INVALIDARG; | |
144 if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /
* , &_matchFinderBase.skipModeBits */)) | |
145 return E_INVALIDARG; break; | |
146 default: | |
147 return E_INVALIDARG; | |
148 } | |
149 } | |
150 return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); | |
151 } | |
152 | |
153 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) | |
154 { | |
155 Byte props[LZMA_PROPS_SIZE]; | |
156 size_t size = LZMA_PROPS_SIZE; | |
157 RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); | |
158 return WriteStream(outStream, props, size); | |
159 } | |
160 | |
161 STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) | |
162 { | |
163 _seqOutStream.RealStream = outStream; | |
164 _seqOutStream.Res = S_OK; | |
165 return S_OK; | |
166 } | |
167 | |
168 STDMETHODIMP CEncoder::ReleaseOutStream() | |
169 { | |
170 _seqOutStream.RealStream.Release(); | |
171 return S_OK; | |
172 } | |
173 | |
174 typedef struct _CCompressProgressImp | |
175 { | |
176 ICompressProgress p; | |
177 ICompressProgressInfo *Progress; | |
178 HRESULT Res; | |
179 } CCompressProgressImp; | |
180 | |
181 #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) | |
182 | |
183 #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) | |
184 | |
185 SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) | |
186 { | |
187 CCompressProgressImp *p = (CCompressProgressImp *)pp; | |
188 p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outS
ize)); | |
189 return (SRes)p->Res; | |
190 } | |
191 | |
192 STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
*outStream, | |
193 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgress
Info *progress) | |
194 { | |
195 CCompressProgressImp progressImp; | |
196 progressImp.p.Progress = CompressProgress; | |
197 progressImp.Progress = progress; | |
198 progressImp.Res = SZ_OK; | |
199 | |
200 _seqInStream.RealStream = inStream; | |
201 SetOutStream(outStream); | |
202 SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream
.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); | |
203 ReleaseOutStream(); | |
204 if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) | |
205 return _seqOutStream.Res; | |
206 if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) | |
207 return progressImp.Res; | |
208 return SResToHRESULT(res); | |
209 } | |
210 | |
211 }} | |
OLD | NEW |