mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 11:14:58 -06:00
145 lines
3.6 KiB
C
Executable File
145 lines
3.6 KiB
C
Executable File
/* 7zDecode.c */
|
|
|
|
#include "7zDecode.h"
|
|
#ifdef _SZ_ONE_DIRECTORY
|
|
#include "LzmaDecode.h"
|
|
#else
|
|
#include "../../Compress/LZMA_C/LzmaDecode.h"
|
|
#endif
|
|
|
|
CMethodID k_Copy = { { 0x0 }, 1 };
|
|
CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
|
|
|
|
#ifdef _LZMA_IN_CB
|
|
|
|
typedef struct _CLzmaInCallbackImp
|
|
{
|
|
ILzmaInCallback InCallback;
|
|
ISzInStream *InStream;
|
|
size_t Size;
|
|
} CLzmaInCallbackImp;
|
|
|
|
int LzmaReadImp(void *object, unsigned char **buffer, UInt32 *size)
|
|
{
|
|
CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
|
|
size_t processedSize;
|
|
SZ_RESULT res;
|
|
*size = 0;
|
|
res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize);
|
|
*size = (UInt32)processedSize;
|
|
if (processedSize > cb->Size)
|
|
return (int)SZE_FAIL;
|
|
cb->Size -= processedSize;
|
|
if (res == SZ_OK)
|
|
return 0;
|
|
return (int)res;
|
|
}
|
|
|
|
#endif
|
|
|
|
SZ_RESULT SzDecode(CFileSize *packSizes, CFolder *folder,
|
|
#ifdef _LZMA_IN_CB
|
|
ISzInStream *inStream,
|
|
#else
|
|
Byte *inBuffer,
|
|
#endif
|
|
Byte *outBuffer, size_t outSize,
|
|
size_t *outSizeProcessed, ISzAlloc *allocMain)
|
|
{
|
|
UInt32 si;
|
|
size_t inSize = 0;
|
|
CCoderInfo *coder;
|
|
if (folder->NumPackStreams != 1)
|
|
return SZE_NOTIMPL;
|
|
if (folder->NumCoders != 1)
|
|
return SZE_NOTIMPL;
|
|
coder = folder->Coders;
|
|
*outSizeProcessed = 0;
|
|
|
|
for (si = 0; si < folder->NumPackStreams; si++)
|
|
inSize += (size_t)packSizes[si];
|
|
|
|
if (AreMethodsEqual(&coder->MethodID, &k_Copy))
|
|
{
|
|
size_t i;
|
|
if (inSize != outSize)
|
|
return SZE_DATA_ERROR;
|
|
#ifdef _LZMA_IN_CB
|
|
for (i = 0; i < inSize;)
|
|
{
|
|
size_t j;
|
|
Byte *inBuffer;
|
|
size_t bufferSize;
|
|
RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize));
|
|
if (bufferSize == 0)
|
|
return SZE_DATA_ERROR;
|
|
if (bufferSize > inSize - i)
|
|
return SZE_FAIL;
|
|
*outSizeProcessed += bufferSize;
|
|
for (j = 0; j < bufferSize && i < inSize; j++, i++)
|
|
outBuffer[i] = inBuffer[j];
|
|
}
|
|
#else
|
|
for (i = 0; i < inSize; i++)
|
|
outBuffer[i] = inBuffer[i];
|
|
*outSizeProcessed = inSize;
|
|
#endif
|
|
return SZ_OK;
|
|
}
|
|
|
|
if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
|
|
{
|
|
#ifdef _LZMA_IN_CB
|
|
CLzmaInCallbackImp lzmaCallback;
|
|
#endif
|
|
|
|
int lc, lp, pb;
|
|
size_t lzmaInternalSize;
|
|
void *lzmaInternalData;
|
|
int result;
|
|
UInt32 outSizeProcessedLoc;
|
|
|
|
#ifdef _LZMA_IN_CB
|
|
lzmaCallback.Size = inSize;
|
|
lzmaCallback.InStream = inStream;
|
|
lzmaCallback.InCallback.Read = LzmaReadImp;
|
|
#endif
|
|
|
|
if (coder->Properties.Capacity < 5)
|
|
return SZE_FAIL;
|
|
lc = (unsigned char)coder->Properties.Items[0];
|
|
if (lc >= (9 * 5 * 5))
|
|
return SZE_FAIL;
|
|
for (pb = 0; lc >= (9 * 5); pb++, lc -= (9 * 5));
|
|
for (lp = 0; lc >= 9; lp++, lc -= 9);
|
|
|
|
lzmaInternalSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * sizeof(CProb);
|
|
lzmaInternalData = allocMain->Alloc(lzmaInternalSize);
|
|
if (lzmaInternalData == 0)
|
|
return SZE_OUTOFMEMORY;
|
|
|
|
result = LzmaDecode((Byte *)lzmaInternalData, (UInt32)lzmaInternalSize,
|
|
lc, lp, pb,
|
|
#ifdef _LZMA_IN_CB
|
|
&lzmaCallback.InCallback,
|
|
#else
|
|
inBuffer, (UInt32)inSize,
|
|
#endif
|
|
outBuffer, (UInt32)outSize,
|
|
&outSizeProcessedLoc);
|
|
*outSizeProcessed = (size_t)outSizeProcessedLoc;
|
|
allocMain->Free(lzmaInternalData);
|
|
/*
|
|
NOT_ENOUGH_MEM error is impossible for this code
|
|
if (result = LZMA_RESULT_NOT_ENOUGH_MEM)
|
|
return SZE_OUTOFMEMORY;
|
|
*/
|
|
if (result == LZMA_RESULT_DATA_ERROR)
|
|
return SZE_DATA_ERROR;
|
|
if (result != LZMA_RESULT_OK)
|
|
return SZE_FAIL;
|
|
return SZ_OK;
|
|
}
|
|
return SZE_NOTIMPL;
|
|
}
|