mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +03:00
154 lines
3.4 KiB
C++
154 lines
3.4 KiB
C++
// Compress/CopyCoder.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "../../../C/Alloc.h"
|
|
|
|
#include "CopyCoder.h"
|
|
|
|
namespace NCompress {
|
|
|
|
static const UInt32 kBufSize = 1 << 17;
|
|
|
|
CCopyCoder::~CCopyCoder()
|
|
{
|
|
::MidFree(_buf);
|
|
}
|
|
|
|
Z7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */))
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
Z7_COM7F_IMF(CCopyCoder::Code(ISequentialInStream *inStream,
|
|
ISequentialOutStream *outStream,
|
|
const UInt64 * /* inSize */, const UInt64 *outSize,
|
|
ICompressProgressInfo *progress))
|
|
{
|
|
if (!_buf)
|
|
{
|
|
_buf = (Byte *)::MidAlloc(kBufSize);
|
|
if (!_buf)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
TotalSize = 0;
|
|
|
|
for (;;)
|
|
{
|
|
UInt32 size = kBufSize;
|
|
if (outSize)
|
|
{
|
|
const UInt64 rem = *outSize - TotalSize;
|
|
if (size > rem)
|
|
{
|
|
size = (UInt32)rem;
|
|
if (size == 0)
|
|
{
|
|
/* if we enable the following check,
|
|
we will make one call of Read(_buf, 0) for empty stream */
|
|
// if (TotalSize != 0)
|
|
return S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT readRes;
|
|
{
|
|
UInt32 pos = 0;
|
|
do
|
|
{
|
|
const UInt32 curSize = size - pos;
|
|
UInt32 processed = 0;
|
|
readRes = inStream->Read(_buf + pos, curSize, &processed);
|
|
if (processed > curSize)
|
|
return E_FAIL; // internal code failure
|
|
pos += processed;
|
|
if (readRes != S_OK || processed == 0)
|
|
break;
|
|
}
|
|
while (pos < kBufSize);
|
|
size = pos;
|
|
}
|
|
|
|
if (size == 0)
|
|
return readRes;
|
|
|
|
if (outStream)
|
|
{
|
|
UInt32 pos = 0;
|
|
do
|
|
{
|
|
const UInt32 curSize = size - pos;
|
|
UInt32 processed = 0;
|
|
const HRESULT res = outStream->Write(_buf + pos, curSize, &processed);
|
|
if (processed > curSize)
|
|
return E_FAIL; // internal code failure
|
|
pos += processed;
|
|
TotalSize += processed;
|
|
RINOK(res)
|
|
if (processed == 0)
|
|
return E_FAIL;
|
|
}
|
|
while (pos < size);
|
|
}
|
|
else
|
|
TotalSize += size;
|
|
|
|
RINOK(readRes)
|
|
|
|
if (size != kBufSize)
|
|
return S_OK;
|
|
|
|
if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0)
|
|
{
|
|
RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize))
|
|
}
|
|
}
|
|
}
|
|
|
|
Z7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream))
|
|
{
|
|
_inStream = inStream;
|
|
TotalSize = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
Z7_COM7F_IMF(CCopyCoder::ReleaseInStream())
|
|
{
|
|
_inStream.Release();
|
|
return S_OK;
|
|
}
|
|
|
|
Z7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
|
|
{
|
|
UInt32 realProcessedSize = 0;
|
|
HRESULT res = _inStream->Read(data, size, &realProcessedSize);
|
|
TotalSize += realProcessedSize;
|
|
if (processedSize)
|
|
*processedSize = realProcessedSize;
|
|
return res;
|
|
}
|
|
|
|
Z7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value))
|
|
{
|
|
*value = TotalSize;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
|
|
{
|
|
CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
|
|
return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
|
|
}
|
|
|
|
HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
|
|
{
|
|
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
|
|
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
|
RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress))
|
|
return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
|
|
}
|
|
|
|
}
|