Консультация № 180911
23.11.2010, 19:33
114.95 руб.
24.11.2010, 17:37
0 6 1
Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:
Прокоментируйте пожалуйста вот этот код.

Код:
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
}

Обсуждение

давно
Профессор
230118
3054
23.11.2010, 22:51
общий
А как можно комментировать, не имея заголовочных файлов, или определения макросов, которые используются. По-видимому, тут распаковывается zip архив. Программа написана в Microsoft VS. Наверное, давно, используются устаревшие макросы.
давно
Посетитель
7438
7205
24.11.2010, 10:14
общий
Адресаты:
Здравствуйте, Асмик.
Так понимаю, речь идет об исходном коде архиватора 7Z
Удачи!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
24.11.2010, 16:52
общий
Находиться в CPP/7z/archive/lzmaHandler.cpp
давно
Профессор
230118
3054
24.11.2010, 16:55
общий
Хотите прокомментировать каждую строку?
Неизвестный
24.11.2010, 17:30
общий
да, можно не очень подробно если чтото понадобиться я еще спрошу. За ранее очень благодарен
давно
Профессор
230118
3054
28.11.2010, 01:01
общий
это ответ
Здравствуйте, Roland Deschain!

Данная функция - реализация интерфейса COM по извлечению архива.
STDMETHODIMP определяется как функция, возвращающая HRESULT.

#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
HRESULT - это тип, который в COM используется для возврата результата работы функции
STDMETHODCALLTYPE определяется как __stdcall - стандартный для С способ вызова аргументов
CHandler - класс, метод которого разбирается(метод называется Extract)
IArchiveExtractCallback - это указатель на интерфейс, функции из которого реализуют непосредственно архивацию
Интерфейс - это определение набора функций, в языке С++ в синтаксисе его нет, поэтому интерфейс в нем - абстрактный класс
COM_TRY_BEGIN определяется как try {
В начале функции проверяются аргументы и возвращается E_INVALIDARG при некорректных данных
extractCallback->SetTotal(_packSize); вызывается функция IArchiveExtractCallback
_packSize - член класса CHandler
CMyComPtr<ISequentialOutStream> realOutStream; - создается выходной поток
Макрос RINOK определяется как
#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; }
CLocalProgress - класс, в котором содержится информация о прогрессе (распаковки)
CXzUnpackerCPP - структура с двумя буферами Byte *InBuf; Byte *OutBuf;
Если создание распаковщика успешно, выделяется память
В цикле из _seqStream читаются данные в xzu.
XzUnpacker_Code получается код распаковщика
Если произошла ошибка или поток перестал читаться, переменная finished устанавливается в true
Полученный буфет записывается в realOutStream
По установке finished в true происходит выход из цикла
После цикла результат переводится в переменную opRes, которая передается в extractCallback->SetOperationResult(opRes)
Возвращается return S_OK;

Форма ответа