5 #include "../../../C/Alloc.h"
\r
7 #include "../../Common/Defs.h"
\r
9 #include "FilterCoder.h"
\r
10 #include "StreamUtils.h"
\r
12 static const UInt32 kBufferSize = 1 << 17;
\r
14 CFilterCoder::CFilterCoder()
\r
16 _buffer = (Byte *)::MidAlloc(kBufferSize);
\r
21 CFilterCoder::~CFilterCoder()
\r
26 HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
\r
28 if (_outSizeIsDefined)
\r
30 UInt64 remSize = _outSize - _nowPos64;
\r
32 size = (UInt32)remSize;
\r
34 RINOK(WriteStream(outStream, _buffer, size));
\r
39 STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
\r
40 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
\r
43 UInt32 bufferPos = 0;
\r
44 _outSizeIsDefined = (outSize != 0);
\r
45 if (_outSizeIsDefined)
\r
46 _outSize = *outSize;
\r
48 while (!_outSizeIsDefined || _nowPos64 < _outSize)
\r
50 size_t processedSize = kBufferSize - bufferPos;
\r
52 // Change it: It can be optimized using ReadPart
\r
53 RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));
\r
55 UInt32 endPos = bufferPos + (UInt32)processedSize;
\r
57 bufferPos = Filter->Filter(_buffer, endPos);
\r
58 if (bufferPos > endPos)
\r
60 for (; endPos < bufferPos; endPos++)
\r
61 _buffer[endPos] = 0;
\r
62 bufferPos = Filter->Filter(_buffer, endPos);
\r
69 return WriteWithLimit(outStream, endPos);
\r
71 RINOK(WriteWithLimit(outStream, bufferPos));
\r
72 if (progress != NULL)
\r
74 RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
\r
77 while (bufferPos < endPos)
\r
78 _buffer[i++] = _buffer[bufferPos++];
\r
84 STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
\r
87 _outStream = outStream;
\r
91 STDMETHODIMP CFilterCoder::ReleaseOutStream()
\r
93 _outStream.Release();
\r
98 STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
\r
100 if (processedSize != NULL)
\r
101 *processedSize = 0;
\r
104 UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos);
\r
105 memcpy(_buffer + _bufferPos, data, sizeTemp);
\r
107 if (processedSize != NULL)
\r
108 *processedSize += sizeTemp;
\r
109 data = (const Byte *)data + sizeTemp;
\r
110 UInt32 endPos = _bufferPos + sizeTemp;
\r
111 _bufferPos = Filter->Filter(_buffer, endPos);
\r
112 if (_bufferPos == 0)
\r
114 _bufferPos = endPos;
\r
117 if (_bufferPos > endPos)
\r
123 RINOK(WriteWithLimit(_outStream, _bufferPos));
\r
125 while (_bufferPos < endPos)
\r
126 _buffer[i++] = _buffer[_bufferPos++];
\r
132 STDMETHODIMP CFilterCoder::Flush()
\r
134 if (_bufferPos != 0)
\r
136 // _buffer contains only data refused by previous Filter->Filter call.
\r
137 UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
\r
138 if (endPos > _bufferPos)
\r
140 for (; _bufferPos < endPos; _bufferPos++)
\r
141 _buffer[_bufferPos] = 0;
\r
142 if (Filter->Filter(_buffer, endPos) != endPos)
\r
145 RINOK(WriteWithLimit(_outStream, _bufferPos));
\r
148 CMyComPtr<IOutStreamFlush> flush;
\r
149 _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
\r
151 return flush->Flush();
\r
156 STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
\r
158 _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
\r
159 _inStream = inStream;
\r
163 STDMETHODIMP CFilterCoder::ReleaseInStream()
\r
165 _inStream.Release();
\r
169 STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
\r
171 if (processedSize != NULL)
\r
172 *processedSize = 0;
\r
175 if (_convertedPosBegin != _convertedPosEnd)
\r
177 UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
\r
178 memcpy(data, _buffer + _convertedPosBegin, sizeTemp);
\r
179 _convertedPosBegin += sizeTemp;
\r
180 data = (void *)((Byte *)data + sizeTemp);
\r
182 if (processedSize != NULL)
\r
183 *processedSize += sizeTemp;
\r
187 for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
\r
188 _buffer[i] = _buffer[_convertedPosEnd + i];
\r
190 _convertedPosBegin = _convertedPosEnd = 0;
\r
191 size_t processedSizeTemp = kBufferSize - _bufferPos;
\r
192 RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp));
\r
193 _bufferPos += (UInt32)processedSizeTemp;
\r
194 _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
\r
195 if (_convertedPosEnd == 0)
\r
197 if (_bufferPos == 0)
\r
199 _convertedPosEnd = _bufferPos; // check it
\r
202 if (_convertedPosEnd > _bufferPos)
\r
204 for (; _bufferPos < _convertedPosEnd; _bufferPos++)
\r
205 _buffer[_bufferPos] = 0;
\r
206 _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
\r
213 STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
\r
215 return _setPassword->CryptoSetPassword(data, size);
\r
219 #ifndef EXTRACT_ONLY
\r
220 STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
\r
221 const PROPVARIANT *properties, UInt32 numProperties)
\r
223 return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
\r
226 STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
\r
228 return _writeCoderProperties->WriteCoderProperties(outStream);
\r
232 STDMETHODIMP CFilterCoder::ResetSalt()
\r
234 return _CryptoResetSalt->ResetSalt();
\r
238 STDMETHODIMP CFilterCoder::ResetInitVector()
\r
240 return _CryptoResetInitVector->ResetInitVector();
\r
244 STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
\r
246 return _setDecoderProperties->SetDecoderProperties2(data, size);
\r