rlm@1: // FilterCoder.cpp rlm@1: rlm@1: #include "StdAfx.h" rlm@1: rlm@1: #include "FilterCoder.h" rlm@1: extern "C" rlm@1: { rlm@1: #include "../../../C/Alloc.h" rlm@1: } rlm@1: #include "../../Common/Defs.h" rlm@1: #include "StreamUtils.h" rlm@1: rlm@1: static const UInt32 kBufferSize = 1 << 17; rlm@1: rlm@1: CFilterCoder::CFilterCoder() rlm@1: { rlm@1: _buffer = (Byte *)::MidAlloc(kBufferSize); rlm@1: } rlm@1: rlm@1: CFilterCoder::~CFilterCoder() rlm@1: { rlm@1: ::MidFree(_buffer); rlm@1: } rlm@1: rlm@1: HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) rlm@1: { rlm@1: if (_outSizeIsDefined) rlm@1: { rlm@1: UInt64 remSize = _outSize - _nowPos64; rlm@1: if (size > remSize) rlm@1: size = (UInt32)remSize; rlm@1: } rlm@1: RINOK(WriteStream(outStream, _buffer, size)); rlm@1: _nowPos64 += size; rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: rlm@1: STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, rlm@1: ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, rlm@1: ICompressProgressInfo *progress) rlm@1: { rlm@1: RINOK(Init()); rlm@1: UInt32 bufferPos = 0; rlm@1: _outSizeIsDefined = (outSize != 0); rlm@1: if (_outSizeIsDefined) rlm@1: _outSize = *outSize; rlm@1: rlm@1: while(NeedMore()) rlm@1: { rlm@1: size_t processedSize = kBufferSize - bufferPos; rlm@1: rlm@1: // Change it: It can be optimized using ReadPart rlm@1: RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); rlm@1: rlm@1: UInt32 endPos = bufferPos + (UInt32)processedSize; rlm@1: rlm@1: bufferPos = Filter->Filter(_buffer, endPos); rlm@1: if (bufferPos > endPos) rlm@1: { rlm@1: for (; endPos< bufferPos; endPos++) rlm@1: _buffer[endPos] = 0; rlm@1: bufferPos = Filter->Filter(_buffer, endPos); rlm@1: } rlm@1: rlm@1: if (bufferPos == 0) rlm@1: { rlm@1: if (endPos > 0) rlm@1: return WriteWithLimit(outStream, endPos); rlm@1: return S_OK; rlm@1: } rlm@1: RINOK(WriteWithLimit(outStream, bufferPos)); rlm@1: if (progress != NULL) rlm@1: { rlm@1: RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); rlm@1: } rlm@1: UInt32 i = 0; rlm@1: while(bufferPos < endPos) rlm@1: _buffer[i++] = _buffer[bufferPos++]; rlm@1: bufferPos = i; rlm@1: } rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: // #ifdef _ST_MODE rlm@1: STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) rlm@1: { rlm@1: _bufferPos = 0; rlm@1: _outStream = outStream; rlm@1: return Init(); rlm@1: } rlm@1: rlm@1: STDMETHODIMP CFilterCoder::ReleaseOutStream() rlm@1: { rlm@1: _outStream.Release(); rlm@1: return S_OK; rlm@1: }; rlm@1: rlm@1: rlm@1: STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) rlm@1: { rlm@1: UInt32 processedSizeTotal = 0; rlm@1: while(size > 0) rlm@1: { rlm@1: UInt32 sizeMax = kBufferSize - _bufferPos; rlm@1: UInt32 sizeTemp = size; rlm@1: if (sizeTemp > sizeMax) rlm@1: sizeTemp = sizeMax; rlm@1: memmove(_buffer + _bufferPos, data, sizeTemp); rlm@1: size -= sizeTemp; rlm@1: processedSizeTotal += sizeTemp; rlm@1: data = (const Byte *)data + sizeTemp; rlm@1: UInt32 endPos = _bufferPos + sizeTemp; rlm@1: _bufferPos = Filter->Filter(_buffer, endPos); rlm@1: if (_bufferPos == 0) rlm@1: { rlm@1: _bufferPos = endPos; rlm@1: break; rlm@1: } rlm@1: if (_bufferPos > endPos) rlm@1: { rlm@1: if (size != 0) rlm@1: return E_FAIL; rlm@1: break; rlm@1: } rlm@1: RINOK(WriteWithLimit(_outStream, _bufferPos)); rlm@1: UInt32 i = 0; rlm@1: while(_bufferPos < endPos) rlm@1: _buffer[i++] = _buffer[_bufferPos++]; rlm@1: _bufferPos = i; rlm@1: } rlm@1: if (processedSize != NULL) rlm@1: *processedSize = processedSizeTotal; rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: STDMETHODIMP CFilterCoder::Flush() rlm@1: { rlm@1: if (_bufferPos != 0) rlm@1: { rlm@1: UInt32 endPos = Filter->Filter(_buffer, _bufferPos); rlm@1: if (endPos > _bufferPos) rlm@1: { rlm@1: for (; _bufferPos < endPos; _bufferPos++) rlm@1: _buffer[_bufferPos] = 0; rlm@1: if (Filter->Filter(_buffer, endPos) != endPos) rlm@1: return E_FAIL; rlm@1: } rlm@1: RINOK(WriteStream(_outStream, _buffer, _bufferPos)); rlm@1: _bufferPos = 0; rlm@1: } rlm@1: CMyComPtr flush; rlm@1: _outStream.QueryInterface(IID_IOutStreamFlush, &flush); rlm@1: if (flush) rlm@1: return flush->Flush(); rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: rlm@1: STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) rlm@1: { rlm@1: _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; rlm@1: _inStream = inStream; rlm@1: return Init(); rlm@1: } rlm@1: rlm@1: STDMETHODIMP CFilterCoder::ReleaseInStream() rlm@1: { rlm@1: _inStream.Release(); rlm@1: return S_OK; rlm@1: }; rlm@1: rlm@1: STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) rlm@1: { rlm@1: UInt32 processedSizeTotal = 0; rlm@1: while(size > 0) rlm@1: { rlm@1: if (_convertedPosBegin != _convertedPosEnd) rlm@1: { rlm@1: UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); rlm@1: memmove(data, _buffer + _convertedPosBegin, sizeTemp); rlm@1: _convertedPosBegin += sizeTemp; rlm@1: data = (void *)((Byte *)data + sizeTemp); rlm@1: size -= sizeTemp; rlm@1: processedSizeTotal += sizeTemp; rlm@1: break; rlm@1: } rlm@1: int i; rlm@1: for (i = 0; _convertedPosEnd + i < _bufferPos; i++) rlm@1: _buffer[i] = _buffer[i + _convertedPosEnd]; rlm@1: _bufferPos = i; rlm@1: _convertedPosBegin = _convertedPosEnd = 0; rlm@1: size_t processedSizeTemp = kBufferSize - _bufferPos; rlm@1: RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); rlm@1: _bufferPos = _bufferPos + (UInt32)processedSizeTemp; rlm@1: _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); rlm@1: if (_convertedPosEnd == 0) rlm@1: { rlm@1: if (_bufferPos == 0) rlm@1: break; rlm@1: else rlm@1: { rlm@1: _convertedPosEnd = _bufferPos; // check it rlm@1: continue; rlm@1: } rlm@1: } rlm@1: if (_convertedPosEnd > _bufferPos) rlm@1: { rlm@1: for (; _bufferPos < _convertedPosEnd; _bufferPos++) rlm@1: _buffer[_bufferPos] = 0; rlm@1: _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); rlm@1: } rlm@1: } rlm@1: if (processedSize != NULL) rlm@1: *processedSize = processedSizeTotal; rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: // #endif // _ST_MODE rlm@1: rlm@1: #ifndef _NO_CRYPTO rlm@1: STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) rlm@1: { rlm@1: return _setPassword->CryptoSetPassword(data, size); rlm@1: } rlm@1: #endif rlm@1: rlm@1: #ifndef EXTRACT_ONLY rlm@1: STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, rlm@1: const PROPVARIANT *properties, UInt32 numProperties) rlm@1: { rlm@1: return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); rlm@1: } rlm@1: rlm@1: STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) rlm@1: { rlm@1: return _writeCoderProperties->WriteCoderProperties(outStream); rlm@1: } rlm@1: rlm@1: /* rlm@1: STDMETHODIMP CFilterCoder::ResetSalt() rlm@1: { rlm@1: return _CryptoResetSalt->ResetSalt(); rlm@1: } rlm@1: */ rlm@1: rlm@1: STDMETHODIMP CFilterCoder::ResetInitVector() rlm@1: { rlm@1: return _CryptoResetInitVector->ResetInitVector(); rlm@1: } rlm@1: #endif rlm@1: rlm@1: STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) rlm@1: { rlm@1: return _setDecoderProperties->SetDecoderProperties2(data, size); rlm@1: } rlm@1: rlm@1: rlm@1: rlm@1: void foo() rlm@1: { rlm@1: }