STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
extractCallback->SetTotal(_packSize);
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
if (_stream)
{
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
}
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
CCompressProgressWrap progressWrap(progress);
SRes res;
const UInt32 kInBufSize = 1 << 15;
const UInt32 kOutBufSize = 1 << 21;
UInt32 inPos = 0;
UInt32 inSize = 0;
UInt32 outPos = 0;
CXzUnpackerCPP xzu;
res = XzUnpacker_Create(&xzu.p, &g_Alloc);
if (res == SZ_OK)
{
xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
if (xzu.InBuf == 0 || xzu.OutBuf == 0)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
for (;;)
{
if (inPos == inSize)
{
inPos = inSize = 0;
RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize));
}
SizeT inLen = inSize - inPos;
SizeT outLen = kOutBufSize - outPos;
ECoderStatus status;
res = XzUnpacker_Code(&xzu.p,
xzu.OutBuf + outPos, &outLen,
xzu.InBuf + inPos, &inLen,
(inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);
// printf("\n_inPos = %6d inLen = %5d, outLen = %5d", inPos, inLen, outLen);
inPos += (UInt32)inLen;
outPos += (UInt32)outLen;
lps->InSize += inLen;
lps->OutSize += outLen;
bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK);
if (outPos == kOutBufSize || finished)
{
if (realOutStream && outPos > 0)
{
RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos));
}
outPos = 0;
}
if (finished)
{
_packSize = lps->InSize;
_unpackSize = lps->OutSize;
_packSizeDefined = _unpackSizeDefined = true;
if (res == SZ_OK)
{
if (status == CODER_STATUS_NEEDS_MORE_INPUT)
{
if (XzUnpacker_IsStreamWasFinished(&xzu.p))
_packSize -= xzu.p.padSize;
else
res = SZ_ERROR_DATA;
}
else
res = SZ_ERROR_DATA;
}
break;
}
RINOK(lps->SetCur());
}
Int32 opRes;
switch(res)
{
case SZ_OK:
opRes = NExtract::NOperationResult::kOK; break;
case SZ_ERROR_UNSUPPORTED:
opRes = NExtract::NOperationResult::kUnSupportedMethod; break;
case SZ_ERROR_CRC:
opRes = NExtract::NOperationResult::kCRCError; break;
case SZ_ERROR_DATA:
case SZ_ERROR_ARCHIVE:
case SZ_ERROR_NO_ARCHIVE:
opRes = NExtract::NOperationResult::kDataError; break;
default:
return SResToHRESULT(res);
}
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
return S_OK;
COM_TRY_END
}
Если Вы уже зарегистрированы на Портале - войдите в систему, если Вы еще не регистрировались - пройдите простую процедуру регистрации.