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