592 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			592 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* 7zDec.c -- Decoding from 7z folder
 | |
| 2017-04-03 : Igor Pavlov : Public domain */
 | |
| 
 | |
| #include "Precomp.h"
 | |
| 
 | |
| #include <string.h>
 | |
| 
 | |
| /* #define _7ZIP_PPMD_SUPPPORT */
 | |
| 
 | |
| #include "7z.h"
 | |
| #include "7zCrc.h"
 | |
| 
 | |
| #include "Bcj2.h"
 | |
| #include "Bra.h"
 | |
| #include "CpuArch.h"
 | |
| #include "Delta.h"
 | |
| #include "LzmaDec.h"
 | |
| #include "Lzma2Dec.h"
 | |
| #ifdef _7ZIP_PPMD_SUPPPORT
 | |
| #include "Ppmd7.h"
 | |
| #endif
 | |
| 
 | |
| #define k_Copy 0
 | |
| #define k_Delta 3
 | |
| #define k_LZMA2 0x21
 | |
| #define k_LZMA  0x30101
 | |
| #define k_BCJ   0x3030103
 | |
| #define k_BCJ2  0x303011B
 | |
| #define k_PPC   0x3030205
 | |
| #define k_IA64  0x3030401
 | |
| #define k_ARM   0x3030501
 | |
| #define k_ARMT  0x3030701
 | |
| #define k_SPARC 0x3030805
 | |
| 
 | |
| 
 | |
| #ifdef _7ZIP_PPMD_SUPPPORT
 | |
| 
 | |
| #define k_PPMD 0x30401
 | |
| 
 | |
| typedef struct
 | |
| {
 | |
|   IByteIn vt;
 | |
|   const Byte *cur;
 | |
|   const Byte *end;
 | |
|   const Byte *begin;
 | |
|   UInt64 processed;
 | |
|   Bool extra;
 | |
|   SRes res;
 | |
|   const ILookInStream *inStream;
 | |
| } CByteInToLook;
 | |
| 
 | |
| static Byte ReadByte(const IByteIn *pp)
 | |
| {
 | |
|   CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
 | |
|   if (p->cur != p->end)
 | |
|     return *p->cur++;
 | |
|   if (p->res == SZ_OK)
 | |
|   {
 | |
|     size_t size = p->cur - p->begin;
 | |
|     p->processed += size;
 | |
|     p->res = ILookInStream_Skip(p->inStream, size);
 | |
|     size = (1 << 25);
 | |
|     p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
 | |
|     p->cur = p->begin;
 | |
|     p->end = p->begin + size;
 | |
|     if (size != 0)
 | |
|       return *p->cur++;;
 | |
|   }
 | |
|   p->extra = True;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream,
 | |
|     Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
 | |
| {
 | |
|   CPpmd7 ppmd;
 | |
|   CByteInToLook s;
 | |
|   SRes res = SZ_OK;
 | |
| 
 | |
|   s.vt.Read = ReadByte;
 | |
|   s.inStream = inStream;
 | |
|   s.begin = s.end = s.cur = NULL;
 | |
|   s.extra = False;
 | |
|   s.res = SZ_OK;
 | |
|   s.processed = 0;
 | |
| 
 | |
|   if (propsSize != 5)
 | |
|     return SZ_ERROR_UNSUPPORTED;
 | |
| 
 | |
|   {
 | |
|     unsigned order = props[0];
 | |
|     UInt32 memSize = GetUi32(props + 1);
 | |
|     if (order < PPMD7_MIN_ORDER ||
 | |
|         order > PPMD7_MAX_ORDER ||
 | |
|         memSize < PPMD7_MIN_MEM_SIZE ||
 | |
|         memSize > PPMD7_MAX_MEM_SIZE)
 | |
|       return SZ_ERROR_UNSUPPORTED;
 | |
|     Ppmd7_Construct(&ppmd);
 | |
|     if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
 | |
|       return SZ_ERROR_MEM;
 | |
|     Ppmd7_Init(&ppmd, order);
 | |
|   }
 | |
|   {
 | |
|     CPpmd7z_RangeDec rc;
 | |
|     Ppmd7z_RangeDec_CreateVTable(&rc);
 | |
|     rc.Stream = &s.vt;
 | |
|     if (!Ppmd7z_RangeDec_Init(&rc))
 | |
|       res = SZ_ERROR_DATA;
 | |
|     else if (s.extra)
 | |
|       res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
 | |
|     else
 | |
|     {
 | |
|       SizeT i;
 | |
|       for (i = 0; i < outSize; i++)
 | |
|       {
 | |
|         int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
 | |
|         if (s.extra || sym < 0)
 | |
|           break;
 | |
|         outBuffer[i] = (Byte)sym;
 | |
|       }
 | |
|       if (i != outSize)
 | |
|         res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
 | |
|       else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
 | |
|         res = SZ_ERROR_DATA;
 | |
|     }
 | |
|   }
 | |
|   Ppmd7_Free(&ppmd, allocMain);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
 | |
|     Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
 | |
| {
 | |
|   CLzmaDec state;
 | |
|   SRes res = SZ_OK;
 | |
| 
 | |
|   LzmaDec_Construct(&state);
 | |
|   RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
 | |
|   state.dic = outBuffer;
 | |
|   state.dicBufSize = outSize;
 | |
|   LzmaDec_Init(&state);
 | |
| 
 | |
|   for (;;)
 | |
|   {
 | |
|     const void *inBuf = NULL;
 | |
|     size_t lookahead = (1 << 18);
 | |
|     if (lookahead > inSize)
 | |
|       lookahead = (size_t)inSize;
 | |
|     res = ILookInStream_Look(inStream, &inBuf, &lookahead);
 | |
|     if (res != SZ_OK)
 | |
|       break;
 | |
| 
 | |
|     {
 | |
|       SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
 | |
|       ELzmaStatus status;
 | |
|       res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
 | |
|       lookahead -= inProcessed;
 | |
|       inSize -= inProcessed;
 | |
|       if (res != SZ_OK)
 | |
|         break;
 | |
| 
 | |
|       if (status == LZMA_STATUS_FINISHED_WITH_MARK)
 | |
|       {
 | |
|         if (outSize != state.dicPos || inSize != 0)
 | |
|           res = SZ_ERROR_DATA;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
 | |
|         break;
 | |
| 
 | |
|       if (inProcessed == 0 && dicPos == state.dicPos)
 | |
|       {
 | |
|         res = SZ_ERROR_DATA;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       res = ILookInStream_Skip(inStream, inProcessed);
 | |
|       if (res != SZ_OK)
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   LzmaDec_FreeProbs(&state, allocMain);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifndef _7Z_NO_METHOD_LZMA2
 | |
| 
 | |
| static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
 | |
|     Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
 | |
| {
 | |
|   CLzma2Dec state;
 | |
|   SRes res = SZ_OK;
 | |
| 
 | |
|   Lzma2Dec_Construct(&state);
 | |
|   if (propsSize != 1)
 | |
|     return SZ_ERROR_DATA;
 | |
|   RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
 | |
|   state.decoder.dic = outBuffer;
 | |
|   state.decoder.dicBufSize = outSize;
 | |
|   Lzma2Dec_Init(&state);
 | |
| 
 | |
|   for (;;)
 | |
|   {
 | |
|     const void *inBuf = NULL;
 | |
|     size_t lookahead = (1 << 18);
 | |
|     if (lookahead > inSize)
 | |
|       lookahead = (size_t)inSize;
 | |
|     res = ILookInStream_Look(inStream, &inBuf, &lookahead);
 | |
|     if (res != SZ_OK)
 | |
|       break;
 | |
| 
 | |
|     {
 | |
|       SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
 | |
|       ELzmaStatus status;
 | |
|       res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
 | |
|       lookahead -= inProcessed;
 | |
|       inSize -= inProcessed;
 | |
|       if (res != SZ_OK)
 | |
|         break;
 | |
| 
 | |
|       if (status == LZMA_STATUS_FINISHED_WITH_MARK)
 | |
|       {
 | |
|         if (outSize != state.decoder.dicPos || inSize != 0)
 | |
|           res = SZ_ERROR_DATA;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (inProcessed == 0 && dicPos == state.decoder.dicPos)
 | |
|       {
 | |
|         res = SZ_ERROR_DATA;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       res = ILookInStream_Skip(inStream, inProcessed);
 | |
|       if (res != SZ_OK)
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Lzma2Dec_FreeProbs(&state, allocMain);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
 | |
| {
 | |
|   while (inSize > 0)
 | |
|   {
 | |
|     const void *inBuf;
 | |
|     size_t curSize = (1 << 18);
 | |
|     if (curSize > inSize)
 | |
|       curSize = (size_t)inSize;
 | |
|     RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
 | |
|     if (curSize == 0)
 | |
|       return SZ_ERROR_INPUT_EOF;
 | |
|     memcpy(outBuffer, inBuf, curSize);
 | |
|     outBuffer += curSize;
 | |
|     inSize -= curSize;
 | |
|     RINOK(ILookInStream_Skip(inStream, curSize));
 | |
|   }
 | |
|   return SZ_OK;
 | |
| }
 | |
| 
 | |
| static Bool IS_MAIN_METHOD(UInt32 m)
 | |
| {
 | |
|   switch (m)
 | |
|   {
 | |
|     case k_Copy:
 | |
|     case k_LZMA:
 | |
|     #ifndef _7Z_NO_METHOD_LZMA2
 | |
|     case k_LZMA2:
 | |
|     #endif
 | |
|     #ifdef _7ZIP_PPMD_SUPPPORT
 | |
|     case k_PPMD:
 | |
|     #endif
 | |
|       return True;
 | |
|   }
 | |
|   return False;
 | |
| }
 | |
| 
 | |
| static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
 | |
| {
 | |
|   return
 | |
|       c->NumStreams == 1
 | |
|       /* && c->MethodID <= (UInt32)0xFFFFFFFF */
 | |
|       && IS_MAIN_METHOD((UInt32)c->MethodID);
 | |
| }
 | |
| 
 | |
| #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
 | |
| 
 | |
| static SRes CheckSupportedFolder(const CSzFolder *f)
 | |
| {
 | |
|   if (f->NumCoders < 1 || f->NumCoders > 4)
 | |
|     return SZ_ERROR_UNSUPPORTED;
 | |
|   if (!IS_SUPPORTED_CODER(&f->Coders[0]))
 | |
|     return SZ_ERROR_UNSUPPORTED;
 | |
|   if (f->NumCoders == 1)
 | |
|   {
 | |
|     if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
 | |
|       return SZ_ERROR_UNSUPPORTED;
 | |
|     return SZ_OK;
 | |
|   }
 | |
|   
 | |
|   
 | |
|   #ifndef _7Z_NO_METHODS_FILTERS
 | |
| 
 | |
|   if (f->NumCoders == 2)
 | |
|   {
 | |
|     const CSzCoderInfo *c = &f->Coders[1];
 | |
|     if (
 | |
|         /* c->MethodID > (UInt32)0xFFFFFFFF || */
 | |
|         c->NumStreams != 1
 | |
|         || f->NumPackStreams != 1
 | |
|         || f->PackStreams[0] != 0
 | |
|         || f->NumBonds != 1
 | |
|         || f->Bonds[0].InIndex != 1
 | |
|         || f->Bonds[0].OutIndex != 0)
 | |
|       return SZ_ERROR_UNSUPPORTED;
 | |
|     switch ((UInt32)c->MethodID)
 | |
|     {
 | |
|       case k_Delta:
 | |
|       case k_BCJ:
 | |
|       case k_PPC:
 | |
|       case k_IA64:
 | |
|       case k_SPARC:
 | |
|       case k_ARM:
 | |
|       case k_ARMT:
 | |
|         break;
 | |
|       default:
 | |
|         return SZ_ERROR_UNSUPPORTED;
 | |
|     }
 | |
|     return SZ_OK;
 | |
|   }
 | |
| 
 | |
|   #endif
 | |
| 
 | |
|   
 | |
|   if (f->NumCoders == 4)
 | |
|   {
 | |
|     if (!IS_SUPPORTED_CODER(&f->Coders[1])
 | |
|         || !IS_SUPPORTED_CODER(&f->Coders[2])
 | |
|         || !IS_BCJ2(&f->Coders[3]))
 | |
|       return SZ_ERROR_UNSUPPORTED;
 | |
|     if (f->NumPackStreams != 4
 | |
|         || f->PackStreams[0] != 2
 | |
|         || f->PackStreams[1] != 6
 | |
|         || f->PackStreams[2] != 1
 | |
|         || f->PackStreams[3] != 0
 | |
|         || f->NumBonds != 3
 | |
|         || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
 | |
|         || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
 | |
|         || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
 | |
|       return SZ_ERROR_UNSUPPORTED;
 | |
|     return SZ_OK;
 | |
|   }
 | |
|   
 | |
|   return SZ_ERROR_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
 | |
| 
 | |
| static SRes SzFolder_Decode2(const CSzFolder *folder,
 | |
|     const Byte *propsData,
 | |
|     const UInt64 *unpackSizes,
 | |
|     const UInt64 *packPositions,
 | |
|     ILookInStream *inStream, UInt64 startPos,
 | |
|     Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
 | |
|     Byte *tempBuf[])
 | |
| {
 | |
|   UInt32 ci;
 | |
|   SizeT tempSizes[3] = { 0, 0, 0};
 | |
|   SizeT tempSize3 = 0;
 | |
|   Byte *tempBuf3 = 0;
 | |
| 
 | |
|   RINOK(CheckSupportedFolder(folder));
 | |
| 
 | |
|   for (ci = 0; ci < folder->NumCoders; ci++)
 | |
|   {
 | |
|     const CSzCoderInfo *coder = &folder->Coders[ci];
 | |
| 
 | |
|     if (IS_MAIN_METHOD((UInt32)coder->MethodID))
 | |
|     {
 | |
|       UInt32 si = 0;
 | |
|       UInt64 offset;
 | |
|       UInt64 inSize;
 | |
|       Byte *outBufCur = outBuffer;
 | |
|       SizeT outSizeCur = outSize;
 | |
|       if (folder->NumCoders == 4)
 | |
|       {
 | |
|         UInt32 indices[] = { 3, 2, 0 };
 | |
|         UInt64 unpackSize = unpackSizes[ci];
 | |
|         si = indices[ci];
 | |
|         if (ci < 2)
 | |
|         {
 | |
|           Byte *temp;
 | |
|           outSizeCur = (SizeT)unpackSize;
 | |
|           if (outSizeCur != unpackSize)
 | |
|             return SZ_ERROR_MEM;
 | |
|           temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
 | |
|           if (!temp && outSizeCur != 0)
 | |
|             return SZ_ERROR_MEM;
 | |
|           outBufCur = tempBuf[1 - ci] = temp;
 | |
|           tempSizes[1 - ci] = outSizeCur;
 | |
|         }
 | |
|         else if (ci == 2)
 | |
|         {
 | |
|           if (unpackSize > outSize) /* check it */
 | |
|             return SZ_ERROR_PARAM;
 | |
|           tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
 | |
|           tempSize3 = outSizeCur = (SizeT)unpackSize;
 | |
|         }
 | |
|         else
 | |
|           return SZ_ERROR_UNSUPPORTED;
 | |
|       }
 | |
|       offset = packPositions[si];
 | |
|       inSize = packPositions[(size_t)si + 1] - offset;
 | |
|       RINOK(LookInStream_SeekTo(inStream, startPos + offset));
 | |
| 
 | |
|       if (coder->MethodID == k_Copy)
 | |
|       {
 | |
|         if (inSize != outSizeCur) /* check it */
 | |
|           return SZ_ERROR_DATA;
 | |
|         RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
 | |
|       }
 | |
|       else if (coder->MethodID == k_LZMA)
 | |
|       {
 | |
|         RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
 | |
|       }
 | |
|       #ifndef _7Z_NO_METHOD_LZMA2
 | |
|       else if (coder->MethodID == k_LZMA2)
 | |
|       {
 | |
|         RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
 | |
|       }
 | |
|       #endif
 | |
|       #ifdef _7ZIP_PPMD_SUPPPORT
 | |
|       else if (coder->MethodID == k_PPMD)
 | |
|       {
 | |
|         RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
 | |
|       }
 | |
|       #endif
 | |
|       else
 | |
|         return SZ_ERROR_UNSUPPORTED;
 | |
|     }
 | |
|     else if (coder->MethodID == k_BCJ2)
 | |
|     {
 | |
|       UInt64 offset = packPositions[1];
 | |
|       UInt64 s3Size = packPositions[2] - offset;
 | |
|       
 | |
|       if (ci != 3)
 | |
|         return SZ_ERROR_UNSUPPORTED;
 | |
|       
 | |
|       tempSizes[2] = (SizeT)s3Size;
 | |
|       if (tempSizes[2] != s3Size)
 | |
|         return SZ_ERROR_MEM;
 | |
|       tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
 | |
|       if (!tempBuf[2] && tempSizes[2] != 0)
 | |
|         return SZ_ERROR_MEM;
 | |
|       
 | |
|       RINOK(LookInStream_SeekTo(inStream, startPos + offset));
 | |
|       RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
 | |
| 
 | |
|       if ((tempSizes[0] & 3) != 0 ||
 | |
|           (tempSizes[1] & 3) != 0 ||
 | |
|           tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
 | |
|         return SZ_ERROR_DATA;
 | |
| 
 | |
|       {
 | |
|         CBcj2Dec p;
 | |
|         
 | |
|         p.bufs[0] = tempBuf3;   p.lims[0] = tempBuf3 + tempSize3;
 | |
|         p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
 | |
|         p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
 | |
|         p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
 | |
|         
 | |
|         p.dest = outBuffer;
 | |
|         p.destLim = outBuffer + outSize;
 | |
|         
 | |
|         Bcj2Dec_Init(&p);
 | |
|         RINOK(Bcj2Dec_Decode(&p));
 | |
| 
 | |
|         {
 | |
|           unsigned i;
 | |
|           for (i = 0; i < 4; i++)
 | |
|             if (p.bufs[i] != p.lims[i])
 | |
|               return SZ_ERROR_DATA;
 | |
|           
 | |
|           if (!Bcj2Dec_IsFinished(&p))
 | |
|             return SZ_ERROR_DATA;
 | |
| 
 | |
|           if (p.dest != p.destLim
 | |
|              || p.state != BCJ2_STREAM_MAIN)
 | |
|             return SZ_ERROR_DATA;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     #ifndef _7Z_NO_METHODS_FILTERS
 | |
|     else if (ci == 1)
 | |
|     {
 | |
|       if (coder->MethodID == k_Delta)
 | |
|       {
 | |
|         if (coder->PropsSize != 1)
 | |
|           return SZ_ERROR_UNSUPPORTED;
 | |
|         {
 | |
|           Byte state[DELTA_STATE_SIZE];
 | |
|           Delta_Init(state);
 | |
|           Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         if (coder->PropsSize != 0)
 | |
|           return SZ_ERROR_UNSUPPORTED;
 | |
|         switch (coder->MethodID)
 | |
|         {
 | |
|           case k_BCJ:
 | |
|           {
 | |
|             UInt32 state;
 | |
|             x86_Convert_Init(state);
 | |
|             x86_Convert(outBuffer, outSize, 0, &state, 0);
 | |
|             break;
 | |
|           }
 | |
|           CASE_BRA_CONV(PPC)
 | |
|           CASE_BRA_CONV(IA64)
 | |
|           CASE_BRA_CONV(SPARC)
 | |
|           CASE_BRA_CONV(ARM)
 | |
|           CASE_BRA_CONV(ARMT)
 | |
|           default:
 | |
|             return SZ_ERROR_UNSUPPORTED;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     #endif
 | |
|     else
 | |
|       return SZ_ERROR_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return SZ_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
 | |
|     ILookInStream *inStream, UInt64 startPos,
 | |
|     Byte *outBuffer, size_t outSize,
 | |
|     ISzAllocPtr allocMain)
 | |
| {
 | |
|   SRes res;
 | |
|   CSzFolder folder;
 | |
|   CSzData sd;
 | |
|   
 | |
|   const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
 | |
|   sd.Data = data;
 | |
|   sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
 | |
|   
 | |
|   res = SzGetNextFolderItem(&folder, &sd);
 | |
|   
 | |
|   if (res != SZ_OK)
 | |
|     return res;
 | |
| 
 | |
|   if (sd.Size != 0
 | |
|       || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
 | |
|       || outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
 | |
|     return SZ_ERROR_FAIL;
 | |
|   {
 | |
|     unsigned i;
 | |
|     Byte *tempBuf[3] = { 0, 0, 0};
 | |
| 
 | |
|     res = SzFolder_Decode2(&folder, data,
 | |
|         &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
 | |
|         p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
 | |
|         inStream, startPos,
 | |
|         outBuffer, (SizeT)outSize, allocMain, tempBuf);
 | |
|     
 | |
|     for (i = 0; i < 3; i++)
 | |
|       ISzAlloc_Free(allocMain, tempBuf[i]);
 | |
| 
 | |
|     if (res == SZ_OK)
 | |
|       if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
 | |
|         if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
 | |
|           res = SZ_ERROR_CRC;
 | |
| 
 | |
|     return res;
 | |
|   }
 | |
| }
 |