rlm@1
|
1 // FilterCoder.cpp
|
rlm@1
|
2
|
rlm@1
|
3 #include "StdAfx.h"
|
rlm@1
|
4
|
rlm@1
|
5 #include "FilterCoder.h"
|
rlm@1
|
6 extern "C"
|
rlm@1
|
7 {
|
rlm@1
|
8 #include "../../../C/Alloc.h"
|
rlm@1
|
9 }
|
rlm@1
|
10 #include "../../Common/Defs.h"
|
rlm@1
|
11 #include "StreamUtils.h"
|
rlm@1
|
12
|
rlm@1
|
13 static const UInt32 kBufferSize = 1 << 17;
|
rlm@1
|
14
|
rlm@1
|
15 CFilterCoder::CFilterCoder()
|
rlm@1
|
16 {
|
rlm@1
|
17 _buffer = (Byte *)::MidAlloc(kBufferSize);
|
rlm@1
|
18 }
|
rlm@1
|
19
|
rlm@1
|
20 CFilterCoder::~CFilterCoder()
|
rlm@1
|
21 {
|
rlm@1
|
22 ::MidFree(_buffer);
|
rlm@1
|
23 }
|
rlm@1
|
24
|
rlm@1
|
25 HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
|
rlm@1
|
26 {
|
rlm@1
|
27 if (_outSizeIsDefined)
|
rlm@1
|
28 {
|
rlm@1
|
29 UInt64 remSize = _outSize - _nowPos64;
|
rlm@1
|
30 if (size > remSize)
|
rlm@1
|
31 size = (UInt32)remSize;
|
rlm@1
|
32 }
|
rlm@1
|
33 RINOK(WriteStream(outStream, _buffer, size));
|
rlm@1
|
34 _nowPos64 += size;
|
rlm@1
|
35 return S_OK;
|
rlm@1
|
36 }
|
rlm@1
|
37
|
rlm@1
|
38
|
rlm@1
|
39 STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
|
rlm@1
|
40 ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
|
rlm@1
|
41 ICompressProgressInfo *progress)
|
rlm@1
|
42 {
|
rlm@1
|
43 RINOK(Init());
|
rlm@1
|
44 UInt32 bufferPos = 0;
|
rlm@1
|
45 _outSizeIsDefined = (outSize != 0);
|
rlm@1
|
46 if (_outSizeIsDefined)
|
rlm@1
|
47 _outSize = *outSize;
|
rlm@1
|
48
|
rlm@1
|
49 while(NeedMore())
|
rlm@1
|
50 {
|
rlm@1
|
51 size_t processedSize = kBufferSize - bufferPos;
|
rlm@1
|
52
|
rlm@1
|
53 // Change it: It can be optimized using ReadPart
|
rlm@1
|
54 RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));
|
rlm@1
|
55
|
rlm@1
|
56 UInt32 endPos = bufferPos + (UInt32)processedSize;
|
rlm@1
|
57
|
rlm@1
|
58 bufferPos = Filter->Filter(_buffer, endPos);
|
rlm@1
|
59 if (bufferPos > endPos)
|
rlm@1
|
60 {
|
rlm@1
|
61 for (; endPos< bufferPos; endPos++)
|
rlm@1
|
62 _buffer[endPos] = 0;
|
rlm@1
|
63 bufferPos = Filter->Filter(_buffer, endPos);
|
rlm@1
|
64 }
|
rlm@1
|
65
|
rlm@1
|
66 if (bufferPos == 0)
|
rlm@1
|
67 {
|
rlm@1
|
68 if (endPos > 0)
|
rlm@1
|
69 return WriteWithLimit(outStream, endPos);
|
rlm@1
|
70 return S_OK;
|
rlm@1
|
71 }
|
rlm@1
|
72 RINOK(WriteWithLimit(outStream, bufferPos));
|
rlm@1
|
73 if (progress != NULL)
|
rlm@1
|
74 {
|
rlm@1
|
75 RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
|
rlm@1
|
76 }
|
rlm@1
|
77 UInt32 i = 0;
|
rlm@1
|
78 while(bufferPos < endPos)
|
rlm@1
|
79 _buffer[i++] = _buffer[bufferPos++];
|
rlm@1
|
80 bufferPos = i;
|
rlm@1
|
81 }
|
rlm@1
|
82 return S_OK;
|
rlm@1
|
83 }
|
rlm@1
|
84
|
rlm@1
|
85 // #ifdef _ST_MODE
|
rlm@1
|
86 STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
|
rlm@1
|
87 {
|
rlm@1
|
88 _bufferPos = 0;
|
rlm@1
|
89 _outStream = outStream;
|
rlm@1
|
90 return Init();
|
rlm@1
|
91 }
|
rlm@1
|
92
|
rlm@1
|
93 STDMETHODIMP CFilterCoder::ReleaseOutStream()
|
rlm@1
|
94 {
|
rlm@1
|
95 _outStream.Release();
|
rlm@1
|
96 return S_OK;
|
rlm@1
|
97 };
|
rlm@1
|
98
|
rlm@1
|
99
|
rlm@1
|
100 STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
rlm@1
|
101 {
|
rlm@1
|
102 UInt32 processedSizeTotal = 0;
|
rlm@1
|
103 while(size > 0)
|
rlm@1
|
104 {
|
rlm@1
|
105 UInt32 sizeMax = kBufferSize - _bufferPos;
|
rlm@1
|
106 UInt32 sizeTemp = size;
|
rlm@1
|
107 if (sizeTemp > sizeMax)
|
rlm@1
|
108 sizeTemp = sizeMax;
|
rlm@1
|
109 memmove(_buffer + _bufferPos, data, sizeTemp);
|
rlm@1
|
110 size -= sizeTemp;
|
rlm@1
|
111 processedSizeTotal += sizeTemp;
|
rlm@1
|
112 data = (const Byte *)data + sizeTemp;
|
rlm@1
|
113 UInt32 endPos = _bufferPos + sizeTemp;
|
rlm@1
|
114 _bufferPos = Filter->Filter(_buffer, endPos);
|
rlm@1
|
115 if (_bufferPos == 0)
|
rlm@1
|
116 {
|
rlm@1
|
117 _bufferPos = endPos;
|
rlm@1
|
118 break;
|
rlm@1
|
119 }
|
rlm@1
|
120 if (_bufferPos > endPos)
|
rlm@1
|
121 {
|
rlm@1
|
122 if (size != 0)
|
rlm@1
|
123 return E_FAIL;
|
rlm@1
|
124 break;
|
rlm@1
|
125 }
|
rlm@1
|
126 RINOK(WriteWithLimit(_outStream, _bufferPos));
|
rlm@1
|
127 UInt32 i = 0;
|
rlm@1
|
128 while(_bufferPos < endPos)
|
rlm@1
|
129 _buffer[i++] = _buffer[_bufferPos++];
|
rlm@1
|
130 _bufferPos = i;
|
rlm@1
|
131 }
|
rlm@1
|
132 if (processedSize != NULL)
|
rlm@1
|
133 *processedSize = processedSizeTotal;
|
rlm@1
|
134 return S_OK;
|
rlm@1
|
135 }
|
rlm@1
|
136
|
rlm@1
|
137 STDMETHODIMP CFilterCoder::Flush()
|
rlm@1
|
138 {
|
rlm@1
|
139 if (_bufferPos != 0)
|
rlm@1
|
140 {
|
rlm@1
|
141 UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
|
rlm@1
|
142 if (endPos > _bufferPos)
|
rlm@1
|
143 {
|
rlm@1
|
144 for (; _bufferPos < endPos; _bufferPos++)
|
rlm@1
|
145 _buffer[_bufferPos] = 0;
|
rlm@1
|
146 if (Filter->Filter(_buffer, endPos) != endPos)
|
rlm@1
|
147 return E_FAIL;
|
rlm@1
|
148 }
|
rlm@1
|
149 RINOK(WriteStream(_outStream, _buffer, _bufferPos));
|
rlm@1
|
150 _bufferPos = 0;
|
rlm@1
|
151 }
|
rlm@1
|
152 CMyComPtr<IOutStreamFlush> flush;
|
rlm@1
|
153 _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
|
rlm@1
|
154 if (flush)
|
rlm@1
|
155 return flush->Flush();
|
rlm@1
|
156 return S_OK;
|
rlm@1
|
157 }
|
rlm@1
|
158
|
rlm@1
|
159
|
rlm@1
|
160 STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
|
rlm@1
|
161 {
|
rlm@1
|
162 _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
|
rlm@1
|
163 _inStream = inStream;
|
rlm@1
|
164 return Init();
|
rlm@1
|
165 }
|
rlm@1
|
166
|
rlm@1
|
167 STDMETHODIMP CFilterCoder::ReleaseInStream()
|
rlm@1
|
168 {
|
rlm@1
|
169 _inStream.Release();
|
rlm@1
|
170 return S_OK;
|
rlm@1
|
171 };
|
rlm@1
|
172
|
rlm@1
|
173 STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
rlm@1
|
174 {
|
rlm@1
|
175 UInt32 processedSizeTotal = 0;
|
rlm@1
|
176 while(size > 0)
|
rlm@1
|
177 {
|
rlm@1
|
178 if (_convertedPosBegin != _convertedPosEnd)
|
rlm@1
|
179 {
|
rlm@1
|
180 UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
|
rlm@1
|
181 memmove(data, _buffer + _convertedPosBegin, sizeTemp);
|
rlm@1
|
182 _convertedPosBegin += sizeTemp;
|
rlm@1
|
183 data = (void *)((Byte *)data + sizeTemp);
|
rlm@1
|
184 size -= sizeTemp;
|
rlm@1
|
185 processedSizeTotal += sizeTemp;
|
rlm@1
|
186 break;
|
rlm@1
|
187 }
|
rlm@1
|
188 int i;
|
rlm@1
|
189 for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
|
rlm@1
|
190 _buffer[i] = _buffer[i + _convertedPosEnd];
|
rlm@1
|
191 _bufferPos = i;
|
rlm@1
|
192 _convertedPosBegin = _convertedPosEnd = 0;
|
rlm@1
|
193 size_t processedSizeTemp = kBufferSize - _bufferPos;
|
rlm@1
|
194 RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp));
|
rlm@1
|
195 _bufferPos = _bufferPos + (UInt32)processedSizeTemp;
|
rlm@1
|
196 _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
rlm@1
|
197 if (_convertedPosEnd == 0)
|
rlm@1
|
198 {
|
rlm@1
|
199 if (_bufferPos == 0)
|
rlm@1
|
200 break;
|
rlm@1
|
201 else
|
rlm@1
|
202 {
|
rlm@1
|
203 _convertedPosEnd = _bufferPos; // check it
|
rlm@1
|
204 continue;
|
rlm@1
|
205 }
|
rlm@1
|
206 }
|
rlm@1
|
207 if (_convertedPosEnd > _bufferPos)
|
rlm@1
|
208 {
|
rlm@1
|
209 for (; _bufferPos < _convertedPosEnd; _bufferPos++)
|
rlm@1
|
210 _buffer[_bufferPos] = 0;
|
rlm@1
|
211 _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
rlm@1
|
212 }
|
rlm@1
|
213 }
|
rlm@1
|
214 if (processedSize != NULL)
|
rlm@1
|
215 *processedSize = processedSizeTotal;
|
rlm@1
|
216 return S_OK;
|
rlm@1
|
217 }
|
rlm@1
|
218
|
rlm@1
|
219 // #endif // _ST_MODE
|
rlm@1
|
220
|
rlm@1
|
221 #ifndef _NO_CRYPTO
|
rlm@1
|
222 STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
rlm@1
|
223 {
|
rlm@1
|
224 return _setPassword->CryptoSetPassword(data, size);
|
rlm@1
|
225 }
|
rlm@1
|
226 #endif
|
rlm@1
|
227
|
rlm@1
|
228 #ifndef EXTRACT_ONLY
|
rlm@1
|
229 STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
|
rlm@1
|
230 const PROPVARIANT *properties, UInt32 numProperties)
|
rlm@1
|
231 {
|
rlm@1
|
232 return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
|
rlm@1
|
233 }
|
rlm@1
|
234
|
rlm@1
|
235 STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
rlm@1
|
236 {
|
rlm@1
|
237 return _writeCoderProperties->WriteCoderProperties(outStream);
|
rlm@1
|
238 }
|
rlm@1
|
239
|
rlm@1
|
240 /*
|
rlm@1
|
241 STDMETHODIMP CFilterCoder::ResetSalt()
|
rlm@1
|
242 {
|
rlm@1
|
243 return _CryptoResetSalt->ResetSalt();
|
rlm@1
|
244 }
|
rlm@1
|
245 */
|
rlm@1
|
246
|
rlm@1
|
247 STDMETHODIMP CFilterCoder::ResetInitVector()
|
rlm@1
|
248 {
|
rlm@1
|
249 return _CryptoResetInitVector->ResetInitVector();
|
rlm@1
|
250 }
|
rlm@1
|
251 #endif
|
rlm@1
|
252
|
rlm@1
|
253 STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
rlm@1
|
254 {
|
rlm@1
|
255 return _setDecoderProperties->SetDecoderProperties2(data, size);
|
rlm@1
|
256 }
|
rlm@1
|
257
|
rlm@1
|
258
|
rlm@1
|
259
|
rlm@1
|
260 void foo()
|
rlm@1
|
261 {
|
rlm@1
|
262 }
|