1370b324cSopenharmony_ci// Compress/CopyCoder.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../C/Alloc.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "CopyCoder.h" 8370b324cSopenharmony_ci 9370b324cSopenharmony_cinamespace NCompress { 10370b324cSopenharmony_ci 11370b324cSopenharmony_cistatic const UInt32 kBufSize = 1 << 17; 12370b324cSopenharmony_ci 13370b324cSopenharmony_ciCCopyCoder::~CCopyCoder() 14370b324cSopenharmony_ci{ 15370b324cSopenharmony_ci ::MidFree(_buf); 16370b324cSopenharmony_ci} 17370b324cSopenharmony_ci 18370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */)) 19370b324cSopenharmony_ci{ 20370b324cSopenharmony_ci return S_OK; 21370b324cSopenharmony_ci} 22370b324cSopenharmony_ci 23370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::Code(ISequentialInStream *inStream, 24370b324cSopenharmony_ci ISequentialOutStream *outStream, 25370b324cSopenharmony_ci const UInt64 * /* inSize */, const UInt64 *outSize, 26370b324cSopenharmony_ci ICompressProgressInfo *progress)) 27370b324cSopenharmony_ci{ 28370b324cSopenharmony_ci if (!_buf) 29370b324cSopenharmony_ci { 30370b324cSopenharmony_ci _buf = (Byte *)::MidAlloc(kBufSize); 31370b324cSopenharmony_ci if (!_buf) 32370b324cSopenharmony_ci return E_OUTOFMEMORY; 33370b324cSopenharmony_ci } 34370b324cSopenharmony_ci 35370b324cSopenharmony_ci TotalSize = 0; 36370b324cSopenharmony_ci 37370b324cSopenharmony_ci for (;;) 38370b324cSopenharmony_ci { 39370b324cSopenharmony_ci UInt32 size = kBufSize; 40370b324cSopenharmony_ci if (outSize) 41370b324cSopenharmony_ci { 42370b324cSopenharmony_ci const UInt64 rem = *outSize - TotalSize; 43370b324cSopenharmony_ci if (size > rem) 44370b324cSopenharmony_ci { 45370b324cSopenharmony_ci size = (UInt32)rem; 46370b324cSopenharmony_ci if (size == 0) 47370b324cSopenharmony_ci { 48370b324cSopenharmony_ci /* if we enable the following check, 49370b324cSopenharmony_ci we will make one call of Read(_buf, 0) for empty stream */ 50370b324cSopenharmony_ci // if (TotalSize != 0) 51370b324cSopenharmony_ci return S_OK; 52370b324cSopenharmony_ci } 53370b324cSopenharmony_ci } 54370b324cSopenharmony_ci } 55370b324cSopenharmony_ci 56370b324cSopenharmony_ci HRESULT readRes; 57370b324cSopenharmony_ci { 58370b324cSopenharmony_ci UInt32 pos = 0; 59370b324cSopenharmony_ci do 60370b324cSopenharmony_ci { 61370b324cSopenharmony_ci const UInt32 curSize = size - pos; 62370b324cSopenharmony_ci UInt32 processed = 0; 63370b324cSopenharmony_ci readRes = inStream->Read(_buf + pos, curSize, &processed); 64370b324cSopenharmony_ci if (processed > curSize) 65370b324cSopenharmony_ci return E_FAIL; // internal code failure 66370b324cSopenharmony_ci pos += processed; 67370b324cSopenharmony_ci if (readRes != S_OK || processed == 0) 68370b324cSopenharmony_ci break; 69370b324cSopenharmony_ci } 70370b324cSopenharmony_ci while (pos < kBufSize); 71370b324cSopenharmony_ci size = pos; 72370b324cSopenharmony_ci } 73370b324cSopenharmony_ci 74370b324cSopenharmony_ci if (size == 0) 75370b324cSopenharmony_ci return readRes; 76370b324cSopenharmony_ci 77370b324cSopenharmony_ci if (outStream) 78370b324cSopenharmony_ci { 79370b324cSopenharmony_ci UInt32 pos = 0; 80370b324cSopenharmony_ci do 81370b324cSopenharmony_ci { 82370b324cSopenharmony_ci const UInt32 curSize = size - pos; 83370b324cSopenharmony_ci UInt32 processed = 0; 84370b324cSopenharmony_ci const HRESULT res = outStream->Write(_buf + pos, curSize, &processed); 85370b324cSopenharmony_ci if (processed > curSize) 86370b324cSopenharmony_ci return E_FAIL; // internal code failure 87370b324cSopenharmony_ci pos += processed; 88370b324cSopenharmony_ci TotalSize += processed; 89370b324cSopenharmony_ci RINOK(res) 90370b324cSopenharmony_ci if (processed == 0) 91370b324cSopenharmony_ci return E_FAIL; 92370b324cSopenharmony_ci } 93370b324cSopenharmony_ci while (pos < size); 94370b324cSopenharmony_ci } 95370b324cSopenharmony_ci else 96370b324cSopenharmony_ci TotalSize += size; 97370b324cSopenharmony_ci 98370b324cSopenharmony_ci RINOK(readRes) 99370b324cSopenharmony_ci 100370b324cSopenharmony_ci if (size != kBufSize) 101370b324cSopenharmony_ci return S_OK; 102370b324cSopenharmony_ci 103370b324cSopenharmony_ci if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0) 104370b324cSopenharmony_ci { 105370b324cSopenharmony_ci RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)) 106370b324cSopenharmony_ci } 107370b324cSopenharmony_ci } 108370b324cSopenharmony_ci} 109370b324cSopenharmony_ci 110370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream)) 111370b324cSopenharmony_ci{ 112370b324cSopenharmony_ci _inStream = inStream; 113370b324cSopenharmony_ci TotalSize = 0; 114370b324cSopenharmony_ci return S_OK; 115370b324cSopenharmony_ci} 116370b324cSopenharmony_ci 117370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::ReleaseInStream()) 118370b324cSopenharmony_ci{ 119370b324cSopenharmony_ci _inStream.Release(); 120370b324cSopenharmony_ci return S_OK; 121370b324cSopenharmony_ci} 122370b324cSopenharmony_ci 123370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)) 124370b324cSopenharmony_ci{ 125370b324cSopenharmony_ci UInt32 realProcessedSize = 0; 126370b324cSopenharmony_ci HRESULT res = _inStream->Read(data, size, &realProcessedSize); 127370b324cSopenharmony_ci TotalSize += realProcessedSize; 128370b324cSopenharmony_ci if (processedSize) 129370b324cSopenharmony_ci *processedSize = realProcessedSize; 130370b324cSopenharmony_ci return res; 131370b324cSopenharmony_ci} 132370b324cSopenharmony_ci 133370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value)) 134370b324cSopenharmony_ci{ 135370b324cSopenharmony_ci *value = TotalSize; 136370b324cSopenharmony_ci return S_OK; 137370b324cSopenharmony_ci} 138370b324cSopenharmony_ci 139370b324cSopenharmony_ciHRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) 140370b324cSopenharmony_ci{ 141370b324cSopenharmony_ci CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder; 142370b324cSopenharmony_ci return copyCoder->Code(inStream, outStream, NULL, NULL, progress); 143370b324cSopenharmony_ci} 144370b324cSopenharmony_ci 145370b324cSopenharmony_ciHRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) 146370b324cSopenharmony_ci{ 147370b324cSopenharmony_ci NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 148370b324cSopenharmony_ci CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 149370b324cSopenharmony_ci RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)) 150370b324cSopenharmony_ci return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; 151370b324cSopenharmony_ci} 152370b324cSopenharmony_ci 153370b324cSopenharmony_ci} 154