mirror of
				https://github.com/facebook/zstd.git
				synced 2025-10-31 08:37:43 +02:00 
			
		
		
		
	Fixed decoding corruption error with quad-symbols huffman on legacy decoders
This commit is contained in:
		| @@ -991,7 +991,6 @@ extern "C" { | |||||||
| ******************************************/ | ******************************************/ | ||||||
| static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | ||||||
| static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */ | static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */ | ||||||
| static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbols decoder */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined (__cplusplus) | #if defined (__cplusplus) | ||||||
| @@ -2371,362 +2370,6 @@ static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, si | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /**********************************/ |  | ||||||
| /* quad-symbol decoding           */ |  | ||||||
| /**********************************/ |  | ||||||
| typedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6; |  | ||||||
| typedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6; |  | ||||||
|  |  | ||||||
| /* recursive, up to level 3; may benefit from <template>-like strategy to nest each level inline */ |  | ||||||
| static void HUF_fillDTableX6LevelN(HUF_DDescX6* DDescription, HUF_DSeqX6* DSequence, int sizeLog, |  | ||||||
|                            const rankVal_t rankValOrigin, const U32 consumed, const int minWeight, const U32 maxWeight, |  | ||||||
|                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, const U32* rankStart, |  | ||||||
|                            const U32 nbBitsBaseline, HUF_DSeqX6 baseSeq, HUF_DDescX6 DDesc) |  | ||||||
| { |  | ||||||
|     const int scaleLog = nbBitsBaseline - sizeLog;   /* note : targetLog >= (nbBitsBaseline-1), hence scaleLog <= 1 */ |  | ||||||
|     const int minBits  = nbBitsBaseline - maxWeight; |  | ||||||
|     const U32 level = DDesc.nbBytes; |  | ||||||
|     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; |  | ||||||
|     U32 symbolStartPos, s; |  | ||||||
|  |  | ||||||
|     /* local rankVal, will be modified */ |  | ||||||
|     memcpy(rankVal, rankValOrigin[consumed], sizeof(rankVal)); |  | ||||||
|  |  | ||||||
|     /* fill skipped values */ |  | ||||||
|     if (minWeight>1) |  | ||||||
|     { |  | ||||||
|         U32 i; |  | ||||||
|         const U32 skipSize = rankVal[minWeight]; |  | ||||||
|         for (i = 0; i < skipSize; i++) |  | ||||||
|         { |  | ||||||
|             DSequence[i] = baseSeq; |  | ||||||
|             DDescription[i] = DDesc; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* fill DTable */ |  | ||||||
|     DDesc.nbBytes++; |  | ||||||
|     symbolStartPos = rankStart[minWeight]; |  | ||||||
|     for (s=symbolStartPos; s<sortedListSize; s++) |  | ||||||
|     { |  | ||||||
|         const BYTE symbol = sortedSymbols[s].symbol; |  | ||||||
|         const U32  weight = sortedSymbols[s].weight;   /* >= 1 (sorted) */ |  | ||||||
|         const int  nbBits = nbBitsBaseline - weight;   /* >= 1 (by construction) */ |  | ||||||
|         const int  totalBits = consumed+nbBits; |  | ||||||
|         const U32  start  = rankVal[weight]; |  | ||||||
|         const U32  length = 1 << (sizeLog-nbBits); |  | ||||||
|         baseSeq.byte[level] = symbol; |  | ||||||
|         DDesc.nbBits = (BYTE)totalBits; |  | ||||||
|  |  | ||||||
|         if ((level<3) && (sizeLog-totalBits >= minBits))   /* enough room for another symbol */ |  | ||||||
|         { |  | ||||||
|             int nextMinWeight = totalBits + scaleLog; |  | ||||||
|             if (nextMinWeight < 1) nextMinWeight = 1; |  | ||||||
|             HUF_fillDTableX6LevelN(DDescription+start, DSequence+start, sizeLog-nbBits, |  | ||||||
|                            rankValOrigin, totalBits, nextMinWeight, maxWeight, |  | ||||||
|                            sortedSymbols, sortedListSize, rankStart, |  | ||||||
|                            nbBitsBaseline, baseSeq, DDesc);   /* recursive (max : level 3) */ |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             U32 i; |  | ||||||
|             const U32 end = start + length; |  | ||||||
|             for (i = start; i < end; i++) |  | ||||||
|             { |  | ||||||
|                 DDescription[i] = DDesc; |  | ||||||
|                 DSequence[i] = baseSeq; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         rankVal[weight] += length; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* note : same preparation as X4 */ |  | ||||||
| static size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize) |  | ||||||
| { |  | ||||||
|     BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1]; |  | ||||||
|     sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1]; |  | ||||||
|     U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 }; |  | ||||||
|     U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 }; |  | ||||||
|     U32* const rankStart = rankStart0+1; |  | ||||||
|     U32 tableLog, maxW, sizeOfSort, nbSymbols; |  | ||||||
|     rankVal_t rankVal; |  | ||||||
|     const U32 memLog = DTable[0]; |  | ||||||
|     const BYTE* ip = (const BYTE*) src; |  | ||||||
|     size_t iSize = ip[0]; |  | ||||||
|  |  | ||||||
|     if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); |  | ||||||
|     //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */ |  | ||||||
|  |  | ||||||
|     iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); |  | ||||||
|     if (HUF_isError(iSize)) return iSize; |  | ||||||
|  |  | ||||||
|     /* check result */ |  | ||||||
|     if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable is too small */ |  | ||||||
|  |  | ||||||
|     /* find maxWeight */ |  | ||||||
|     for (maxW = tableLog; rankStats[maxW]==0; maxW--) |  | ||||||
|         { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */ |  | ||||||
|  |  | ||||||
|     /* Get start index of each weight */ |  | ||||||
|     { |  | ||||||
|         U32 w, nextRankStart = 0; |  | ||||||
|         for (w=1; w<=maxW; w++) |  | ||||||
|         { |  | ||||||
|             U32 current = nextRankStart; |  | ||||||
|             nextRankStart += rankStats[w]; |  | ||||||
|             rankStart[w] = current; |  | ||||||
|         } |  | ||||||
|         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/ |  | ||||||
|         sizeOfSort = nextRankStart; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* sort symbols by weight */ |  | ||||||
|     { |  | ||||||
|         U32 s; |  | ||||||
|         for (s=0; s<nbSymbols; s++) |  | ||||||
|         { |  | ||||||
|             U32 w = weightList[s]; |  | ||||||
|             U32 r = rankStart[w]++; |  | ||||||
|             sortedSymbol[r].symbol = (BYTE)s; |  | ||||||
|             sortedSymbol[r].weight = (BYTE)w; |  | ||||||
|         } |  | ||||||
|         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	/* Build rankVal */ |  | ||||||
|     { |  | ||||||
|         const U32 minBits = tableLog+1 - maxW; |  | ||||||
|         U32 nextRankVal = 0; |  | ||||||
|         U32 w, consumed; |  | ||||||
|         const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */ |  | ||||||
|         U32* rankVal0 = rankVal[0]; |  | ||||||
|         for (w=1; w<=maxW; w++) |  | ||||||
|         { |  | ||||||
|             U32 current = nextRankVal; |  | ||||||
|             nextRankVal += rankStats[w] << (w+rescale); |  | ||||||
|             rankVal0[w] = current; |  | ||||||
|         } |  | ||||||
|         for (consumed = minBits; consumed <= memLog - minBits; consumed++) |  | ||||||
|         { |  | ||||||
|             U32* rankValPtr = rankVal[consumed]; |  | ||||||
|             for (w = 1; w <= maxW; w++) |  | ||||||
|             { |  | ||||||
|                 rankValPtr[w] = rankVal0[w] >> consumed; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /* fill tables */ |  | ||||||
|     { |  | ||||||
|         void* ddPtr = DTable+1; |  | ||||||
|         HUF_DDescX6* DDescription = (HUF_DDescX6*)(ddPtr); |  | ||||||
|         void* dsPtr = DTable + 1 + ((size_t)1<<(memLog-1)); |  | ||||||
|         HUF_DSeqX6* DSequence = (HUF_DSeqX6*)(dsPtr); |  | ||||||
|         HUF_DSeqX6 DSeq; |  | ||||||
|         HUF_DDescX6 DDesc; |  | ||||||
|         DSeq.sequence = 0; |  | ||||||
|         DDesc.nbBits = 0; |  | ||||||
|         DDesc.nbBytes = 0; |  | ||||||
|         HUF_fillDTableX6LevelN(DDescription, DSequence, memLog, |  | ||||||
|                        (const U32 (*)[HUF_ABSOLUTEMAX_TABLELOG + 1])rankVal, 0, 1, maxW, |  | ||||||
|                        sortedSymbol, sizeOfSort, rankStart0, |  | ||||||
|                        tableLog+1, DSeq, DDesc); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return iSize; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static U32 HUF_decodeSymbolX6(void* op, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */ |  | ||||||
|     memcpy(op, ds+val, sizeof(HUF_DSeqX6)); |  | ||||||
|     BIT_skipBits(DStream, dd[val].nbBits); |  | ||||||
|     return dd[val].nbBytes; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static U32 HUF_decodeLastSymbolsX6(void* op, const U32 maxL, BIT_DStream_t* DStream, |  | ||||||
|                                   const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */ |  | ||||||
|     U32 length = dd[val].nbBytes; |  | ||||||
|     if (length <= maxL) |  | ||||||
|     { |  | ||||||
|         memcpy(op, ds+val, length); |  | ||||||
|         BIT_skipBits(DStream, dd[val].nbBits); |  | ||||||
|         return length; |  | ||||||
|     } |  | ||||||
|     memcpy(op, ds+val, maxL); |  | ||||||
|     if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) |  | ||||||
|     { |  | ||||||
|         BIT_skipBits(DStream, dd[val].nbBits); |  | ||||||
|         if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) |  | ||||||
|             DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ |  | ||||||
|     } |  | ||||||
|     return maxL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) \ |  | ||||||
|     ptr += HUF_decodeSymbolX6(ptr, DStreamPtr, dd, ds, dtLog) |  | ||||||
|  |  | ||||||
| #define HUF_DECODE_SYMBOLX6_1(ptr, DStreamPtr) \ |  | ||||||
|     if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) |  | ||||||
|  |  | ||||||
| #define HUF_DECODE_SYMBOLX6_2(ptr, DStreamPtr) \ |  | ||||||
|     if (MEM_64bits()) \ |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) |  | ||||||
|  |  | ||||||
| static inline size_t HUF_decodeStreamX6(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const U32* DTable, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const void* ddPtr = DTable+1; |  | ||||||
|     const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr); |  | ||||||
|     const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); |  | ||||||
|     const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr); |  | ||||||
|     BYTE* const pStart = p; |  | ||||||
|  |  | ||||||
|     /* up to 16 symbols at a time */ |  | ||||||
|     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-16)) |  | ||||||
|     { |  | ||||||
|         HUF_DECODE_SYMBOLX6_2(p, bitDPtr); |  | ||||||
|         HUF_DECODE_SYMBOLX6_1(p, bitDPtr); |  | ||||||
|         HUF_DECODE_SYMBOLX6_2(p, bitDPtr); |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(p, bitDPtr); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* closer to the end, up to 4 symbols at a time */ |  | ||||||
|     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(p, bitDPtr); |  | ||||||
|  |  | ||||||
|     while (p <= pEnd-4) |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */ |  | ||||||
|  |  | ||||||
|     while (p < pEnd) |  | ||||||
|         p += HUF_decodeLastSymbolsX6(p, (U32)(pEnd-p), bitDPtr, dd, ds, dtLog); |  | ||||||
|  |  | ||||||
|     return p-pStart; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static size_t HUF_decompress4X6_usingDTable( |  | ||||||
|           void* dst,  size_t dstSize, |  | ||||||
|     const void* cSrc, size_t cSrcSize, |  | ||||||
|     const U32* DTable) |  | ||||||
| { |  | ||||||
|     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */ |  | ||||||
|  |  | ||||||
|     { |  | ||||||
|         const BYTE* const istart = (const BYTE*) cSrc; |  | ||||||
|         BYTE* const ostart = (BYTE*) dst; |  | ||||||
|         BYTE* const oend = ostart + dstSize; |  | ||||||
|  |  | ||||||
|         const U32 dtLog = DTable[0]; |  | ||||||
|         const void* ddPtr = DTable+1; |  | ||||||
|         const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr); |  | ||||||
|         const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); |  | ||||||
|         const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr); |  | ||||||
|         size_t errorCode; |  | ||||||
|  |  | ||||||
|         /* Init */ |  | ||||||
|         BIT_DStream_t bitD1; |  | ||||||
|         BIT_DStream_t bitD2; |  | ||||||
|         BIT_DStream_t bitD3; |  | ||||||
|         BIT_DStream_t bitD4; |  | ||||||
|         const size_t length1 = MEM_readLE16(istart); |  | ||||||
|         const size_t length2 = MEM_readLE16(istart+2); |  | ||||||
|         const size_t length3 = MEM_readLE16(istart+4); |  | ||||||
|         size_t length4; |  | ||||||
|         const BYTE* const istart1 = istart + 6;  /* jumpTable */ |  | ||||||
|         const BYTE* const istart2 = istart1 + length1; |  | ||||||
|         const BYTE* const istart3 = istart2 + length2; |  | ||||||
|         const BYTE* const istart4 = istart3 + length3; |  | ||||||
|         const size_t segmentSize = (dstSize+3) / 4; |  | ||||||
|         BYTE* const opStart2 = ostart + segmentSize; |  | ||||||
|         BYTE* const opStart3 = opStart2 + segmentSize; |  | ||||||
|         BYTE* const opStart4 = opStart3 + segmentSize; |  | ||||||
|         BYTE* op1 = ostart; |  | ||||||
|         BYTE* op2 = opStart2; |  | ||||||
|         BYTE* op3 = opStart3; |  | ||||||
|         BYTE* op4 = opStart4; |  | ||||||
|         U32 endSignal; |  | ||||||
|  |  | ||||||
|         length4 = cSrcSize - (length1 + length2 + length3 + 6); |  | ||||||
|         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */ |  | ||||||
|         errorCode = BIT_initDStream(&bitD1, istart1, length1); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|         errorCode = BIT_initDStream(&bitD2, istart2, length2); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|         errorCode = BIT_initDStream(&bitD3, istart3, length3); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|         errorCode = BIT_initDStream(&bitD4, istart4, length4); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|  |  | ||||||
|         /* 16-64 symbols per loop (4-16 symbols per stream) */ |  | ||||||
|         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); |  | ||||||
|         for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; ) |  | ||||||
|         { |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op4, &bitD4); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op4, &bitD4); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op4, &bitD4); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op4, &bitD4); |  | ||||||
|  |  | ||||||
|             endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /* check corruption */ |  | ||||||
|         if (op1 > opStart2) return ERROR(corruption_detected); |  | ||||||
|         if (op2 > opStart3) return ERROR(corruption_detected); |  | ||||||
|         if (op3 > opStart4) return ERROR(corruption_detected); |  | ||||||
|         /* note : op4 supposed already verified within main loop */ |  | ||||||
|  |  | ||||||
|         /* finish bitStreams one by one */ |  | ||||||
|         HUF_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog); |  | ||||||
|         HUF_decodeStreamX6(op2, &bitD2, opStart3, DTable, dtLog); |  | ||||||
|         HUF_decodeStreamX6(op3, &bitD3, opStart4, DTable, dtLog); |  | ||||||
|         HUF_decodeStreamX6(op4, &bitD4, oend,     DTable, dtLog); |  | ||||||
|  |  | ||||||
|         /* check */ |  | ||||||
|         endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); |  | ||||||
|         if (!endSignal) return ERROR(corruption_detected); |  | ||||||
|  |  | ||||||
|         /* decoded size */ |  | ||||||
|         return dstSize; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) |  | ||||||
| { |  | ||||||
|     HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG); |  | ||||||
|     const BYTE* ip = (const BYTE*) cSrc; |  | ||||||
|  |  | ||||||
|     size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize); |  | ||||||
|     if (HUF_isError(hSize)) return hSize; |  | ||||||
|     if (hSize >= cSrcSize) return ERROR(srcSize_wrong); |  | ||||||
|     ip += hSize; |  | ||||||
|     cSrcSize -= hSize; |  | ||||||
|  |  | ||||||
|     return HUF_decompress4X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /**********************************/ | /**********************************/ | ||||||
| /* Generic decompression selector */ | /* Generic decompression selector */ | ||||||
| /**********************************/ | /**********************************/ | ||||||
| @@ -2757,7 +2400,7 @@ typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, | |||||||
|  |  | ||||||
| static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) | static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) | ||||||
| { | { | ||||||
|     static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, HUF_decompress4X6 }; |     static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL }; | ||||||
|     /* estimate decompression time */ |     /* estimate decompression time */ | ||||||
|     U32 Q; |     U32 Q; | ||||||
|     const U32 D256 = (U32)(dstSize >> 8); |     const U32 D256 = (U32)(dstSize >> 8); | ||||||
| @@ -2779,7 +2422,6 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_ | |||||||
|     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ |     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ | ||||||
|  |  | ||||||
|     if (Dtime[1] < Dtime[0]) algoNb = 1; |     if (Dtime[1] < Dtime[0]) algoNb = 1; | ||||||
|     if (Dtime[2] < Dtime[algoNb]) algoNb = 2; |  | ||||||
|  |  | ||||||
|     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); |     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2023,7 +2023,6 @@ extern "C" { | |||||||
| ******************************************/ | ******************************************/ | ||||||
| static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | ||||||
| static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */ | static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */ | ||||||
| static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbols decoder */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* **************************************** | /* **************************************** | ||||||
| @@ -2038,11 +2037,9 @@ HUF_decompress() does the following: | |||||||
| */ | */ | ||||||
| static size_t HUF_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize); | static size_t HUF_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize); | ||||||
| static size_t HUF_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize); | static size_t HUF_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize); | ||||||
| static size_t HUF_readDTableX6 (unsigned* DTable, const void* src, size_t srcSize); |  | ||||||
|  |  | ||||||
| static size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); | static size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); | ||||||
| static size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); | static size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); | ||||||
| static size_t HUF_decompress4X6_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined (__cplusplus) | #if defined (__cplusplus) | ||||||
| @@ -2793,356 +2790,6 @@ static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, si | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /**********************************/ |  | ||||||
| /* quad-symbol decoding           */ |  | ||||||
| /**********************************/ |  | ||||||
| typedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6; |  | ||||||
| typedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6; |  | ||||||
|  |  | ||||||
| /* recursive, up to level 3; may benefit from <template>-like strategy to nest each level inline */ |  | ||||||
| static void HUF_fillDTableX6LevelN(HUF_DDescX6* DDescription, HUF_DSeqX6* DSequence, int sizeLog, |  | ||||||
|                            const rankVal_t rankValOrigin, const U32 consumed, const int minWeight, const U32 maxWeight, |  | ||||||
|                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, const U32* rankStart, |  | ||||||
|                            const U32 nbBitsBaseline, HUF_DSeqX6 baseSeq, HUF_DDescX6 DDesc) |  | ||||||
| { |  | ||||||
|     const int scaleLog = nbBitsBaseline - sizeLog;   /* note : targetLog >= (nbBitsBaseline-1), hence scaleLog <= 1 */ |  | ||||||
|     const int minBits  = nbBitsBaseline - maxWeight; |  | ||||||
|     const U32 level = DDesc.nbBytes; |  | ||||||
|     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; |  | ||||||
|     U32 symbolStartPos, s; |  | ||||||
|  |  | ||||||
|     /* local rankVal, will be modified */ |  | ||||||
|     memcpy(rankVal, rankValOrigin[consumed], sizeof(rankVal)); |  | ||||||
|  |  | ||||||
|     /* fill skipped values */ |  | ||||||
|     if (minWeight>1) |  | ||||||
|     { |  | ||||||
|         U32 i; |  | ||||||
|         const U32 skipSize = rankVal[minWeight]; |  | ||||||
|         for (i = 0; i < skipSize; i++) |  | ||||||
|         { |  | ||||||
|             DSequence[i] = baseSeq; |  | ||||||
|             DDescription[i] = DDesc; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* fill DTable */ |  | ||||||
|     DDesc.nbBytes++; |  | ||||||
|     symbolStartPos = rankStart[minWeight]; |  | ||||||
|     for (s=symbolStartPos; s<sortedListSize; s++) |  | ||||||
|     { |  | ||||||
|         const BYTE symbol = sortedSymbols[s].symbol; |  | ||||||
|         const U32  weight = sortedSymbols[s].weight;   /* >= 1 (sorted) */ |  | ||||||
|         const int  nbBits = nbBitsBaseline - weight;   /* >= 1 (by construction) */ |  | ||||||
|         const int  totalBits = consumed+nbBits; |  | ||||||
|         const U32  start  = rankVal[weight]; |  | ||||||
|         const U32  length = 1 << (sizeLog-nbBits); |  | ||||||
|         baseSeq.byte[level] = symbol; |  | ||||||
|         DDesc.nbBits = (BYTE)totalBits; |  | ||||||
|  |  | ||||||
|         if ((level<3) && (sizeLog-totalBits >= minBits))   /* enough room for another symbol */ |  | ||||||
|         { |  | ||||||
|             int nextMinWeight = totalBits + scaleLog; |  | ||||||
|             if (nextMinWeight < 1) nextMinWeight = 1; |  | ||||||
|             HUF_fillDTableX6LevelN(DDescription+start, DSequence+start, sizeLog-nbBits, |  | ||||||
|                            rankValOrigin, totalBits, nextMinWeight, maxWeight, |  | ||||||
|                            sortedSymbols, sortedListSize, rankStart, |  | ||||||
|                            nbBitsBaseline, baseSeq, DDesc);   /* recursive (max : level 3) */ |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             U32 i; |  | ||||||
|             const U32 end = start + length; |  | ||||||
|             for (i = start; i < end; i++) |  | ||||||
|             { |  | ||||||
|                 DDescription[i] = DDesc; |  | ||||||
|                 DSequence[i] = baseSeq; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         rankVal[weight] += length; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* note : same preparation as X4 */ |  | ||||||
| static size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize) |  | ||||||
| { |  | ||||||
|     BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1]; |  | ||||||
|     sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1]; |  | ||||||
|     U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 }; |  | ||||||
|     U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 }; |  | ||||||
|     U32* const rankStart = rankStart0+1; |  | ||||||
|     U32 tableLog, maxW, sizeOfSort, nbSymbols; |  | ||||||
|     rankVal_t rankVal; |  | ||||||
|     const U32 memLog = DTable[0]; |  | ||||||
|     size_t iSize; |  | ||||||
|  |  | ||||||
|     if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); |  | ||||||
|     //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */ |  | ||||||
|  |  | ||||||
|     iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); |  | ||||||
|     if (HUF_isError(iSize)) return iSize; |  | ||||||
|  |  | ||||||
|     /* check result */ |  | ||||||
|     if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable is too small */ |  | ||||||
|  |  | ||||||
|     /* find maxWeight */ |  | ||||||
|     for (maxW = tableLog; rankStats[maxW]==0; maxW--) |  | ||||||
|         { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */ |  | ||||||
|  |  | ||||||
|     /* Get start index of each weight */ |  | ||||||
|     { |  | ||||||
|         U32 w, nextRankStart = 0; |  | ||||||
|         for (w=1; w<=maxW; w++) |  | ||||||
|         { |  | ||||||
|             U32 current = nextRankStart; |  | ||||||
|             nextRankStart += rankStats[w]; |  | ||||||
|             rankStart[w] = current; |  | ||||||
|         } |  | ||||||
|         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/ |  | ||||||
|         sizeOfSort = nextRankStart; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* sort symbols by weight */ |  | ||||||
|     { |  | ||||||
|         U32 s; |  | ||||||
|         for (s=0; s<nbSymbols; s++) |  | ||||||
|         { |  | ||||||
|             U32 w = weightList[s]; |  | ||||||
|             U32 r = rankStart[w]++; |  | ||||||
|             sortedSymbol[r].symbol = (BYTE)s; |  | ||||||
|             sortedSymbol[r].weight = (BYTE)w; |  | ||||||
|         } |  | ||||||
|         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Build rankVal */ |  | ||||||
|     { |  | ||||||
|         const U32 minBits = tableLog+1 - maxW; |  | ||||||
|         U32 nextRankVal = 0; |  | ||||||
|         U32 w, consumed; |  | ||||||
|         const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */ |  | ||||||
|         U32* rankVal0 = rankVal[0]; |  | ||||||
|         for (w=1; w<=maxW; w++) |  | ||||||
|         { |  | ||||||
|             U32 current = nextRankVal; |  | ||||||
|             nextRankVal += rankStats[w] << (w+rescale); |  | ||||||
|             rankVal0[w] = current; |  | ||||||
|         } |  | ||||||
|         for (consumed = minBits; consumed <= memLog - minBits; consumed++) |  | ||||||
|         { |  | ||||||
|             U32* rankValPtr = rankVal[consumed]; |  | ||||||
|             for (w = 1; w <= maxW; w++) |  | ||||||
|             { |  | ||||||
|                 rankValPtr[w] = rankVal0[w] >> consumed; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* fill tables */ |  | ||||||
|     { |  | ||||||
|         void* ddPtr = DTable+1; |  | ||||||
|         HUF_DDescX6* DDescription = (HUF_DDescX6*)ddPtr; |  | ||||||
|         void* dsPtr = DTable + 1 + ((size_t)1<<(memLog-1)); |  | ||||||
|         HUF_DSeqX6* DSequence = (HUF_DSeqX6*)dsPtr; |  | ||||||
|         HUF_DSeqX6 DSeq; |  | ||||||
|         HUF_DDescX6 DDesc; |  | ||||||
|         DSeq.sequence = 0; |  | ||||||
|         DDesc.nbBits = 0; |  | ||||||
|         DDesc.nbBytes = 0; |  | ||||||
|         HUF_fillDTableX6LevelN(DDescription, DSequence, memLog, |  | ||||||
|                        (const U32 (*)[HUF_ABSOLUTEMAX_TABLELOG + 1])rankVal, 0, 1, maxW, |  | ||||||
|                        sortedSymbol, sizeOfSort, rankStart0, |  | ||||||
|                        tableLog+1, DSeq, DDesc); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return iSize; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static U32 HUF_decodeSymbolX6(void* op, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */ |  | ||||||
|     memcpy(op, ds+val, sizeof(HUF_DSeqX6)); |  | ||||||
|     BIT_skipBits(DStream, dd[val].nbBits); |  | ||||||
|     return dd[val].nbBytes; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static U32 HUF_decodeLastSymbolsX6(void* op, const U32 maxL, BIT_DStream_t* DStream, |  | ||||||
|                                   const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */ |  | ||||||
|     U32 length = dd[val].nbBytes; |  | ||||||
|     if (length <= maxL) |  | ||||||
|     { |  | ||||||
|         memcpy(op, ds+val, length); |  | ||||||
|         BIT_skipBits(DStream, dd[val].nbBits); |  | ||||||
|         return length; |  | ||||||
|     } |  | ||||||
|     memcpy(op, ds+val, maxL); |  | ||||||
|     if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) |  | ||||||
|     { |  | ||||||
|         BIT_skipBits(DStream, dd[val].nbBits); |  | ||||||
|         if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) |  | ||||||
|             DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ |  | ||||||
|     } |  | ||||||
|     return maxL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) \ |  | ||||||
|     ptr += HUF_decodeSymbolX6(ptr, DStreamPtr, dd, ds, dtLog) |  | ||||||
|  |  | ||||||
| #define HUF_DECODE_SYMBOLX6_1(ptr, DStreamPtr) \ |  | ||||||
|     if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) |  | ||||||
|  |  | ||||||
| #define HUF_DECODE_SYMBOLX6_2(ptr, DStreamPtr) \ |  | ||||||
|     if (MEM_64bits()) \ |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) |  | ||||||
|  |  | ||||||
| static inline size_t HUF_decodeStreamX6(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const U32* DTable, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const void* const ddPtr = DTable+1; |  | ||||||
|     const HUF_DDescX6* dd = (const HUF_DDescX6*)ddPtr; |  | ||||||
|     const void* const dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); |  | ||||||
|     const HUF_DSeqX6* ds = (const HUF_DSeqX6*)dsPtr; |  | ||||||
|     BYTE* const pStart = p; |  | ||||||
|  |  | ||||||
|     /* up to 16 symbols at a time */ |  | ||||||
|     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-16)) |  | ||||||
|     { |  | ||||||
|         HUF_DECODE_SYMBOLX6_2(p, bitDPtr); |  | ||||||
|         HUF_DECODE_SYMBOLX6_1(p, bitDPtr); |  | ||||||
|         HUF_DECODE_SYMBOLX6_2(p, bitDPtr); |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(p, bitDPtr); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* closer to the end, up to 4 symbols at a time */ |  | ||||||
|     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) |  | ||||||
|         HUF_DECODE_SYMBOLX6_0(p, bitDPtr); |  | ||||||
|  |  | ||||||
|     while ((BIT_reloadDStream(bitDPtr) <= BIT_DStream_endOfBuffer) && (p < pEnd)) |  | ||||||
|         p += HUF_decodeLastSymbolsX6(p, (U32)(pEnd-p), bitDPtr, dd, ds, dtLog); |  | ||||||
|  |  | ||||||
|     return p-pStart; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static size_t HUF_decompress4X6_usingDTable( |  | ||||||
|           void* dst,  size_t dstSize, |  | ||||||
|     const void* cSrc, size_t cSrcSize, |  | ||||||
|     const U32* DTable) |  | ||||||
| { |  | ||||||
|     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */ |  | ||||||
|  |  | ||||||
|     { |  | ||||||
|         const BYTE* const istart = (const BYTE*) cSrc; |  | ||||||
|         BYTE* const ostart = (BYTE*) dst; |  | ||||||
|         BYTE* const oend = ostart + dstSize; |  | ||||||
|  |  | ||||||
|         const U32 dtLog = DTable[0]; |  | ||||||
|         const void* const ddPtr = DTable+1; |  | ||||||
|         const HUF_DDescX6* dd = (const HUF_DDescX6*)ddPtr; |  | ||||||
|         const void* const dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); |  | ||||||
|         const HUF_DSeqX6* ds = (const HUF_DSeqX6*)dsPtr; |  | ||||||
|         size_t errorCode; |  | ||||||
|  |  | ||||||
|         /* Init */ |  | ||||||
|         BIT_DStream_t bitD1; |  | ||||||
|         BIT_DStream_t bitD2; |  | ||||||
|         BIT_DStream_t bitD3; |  | ||||||
|         BIT_DStream_t bitD4; |  | ||||||
|         const size_t length1 = MEM_readLE16(istart); |  | ||||||
|         const size_t length2 = MEM_readLE16(istart+2); |  | ||||||
|         const size_t length3 = MEM_readLE16(istart+4); |  | ||||||
|         size_t length4; |  | ||||||
|         const BYTE* const istart1 = istart + 6;  /* jumpTable */ |  | ||||||
|         const BYTE* const istart2 = istart1 + length1; |  | ||||||
|         const BYTE* const istart3 = istart2 + length2; |  | ||||||
|         const BYTE* const istart4 = istart3 + length3; |  | ||||||
|         const size_t segmentSize = (dstSize+3) / 4; |  | ||||||
|         BYTE* const opStart2 = ostart + segmentSize; |  | ||||||
|         BYTE* const opStart3 = opStart2 + segmentSize; |  | ||||||
|         BYTE* const opStart4 = opStart3 + segmentSize; |  | ||||||
|         BYTE* op1 = ostart; |  | ||||||
|         BYTE* op2 = opStart2; |  | ||||||
|         BYTE* op3 = opStart3; |  | ||||||
|         BYTE* op4 = opStart4; |  | ||||||
|         U32 endSignal; |  | ||||||
|  |  | ||||||
|         length4 = cSrcSize - (length1 + length2 + length3 + 6); |  | ||||||
|         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */ |  | ||||||
|         errorCode = BIT_initDStream(&bitD1, istart1, length1); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|         errorCode = BIT_initDStream(&bitD2, istart2, length2); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|         errorCode = BIT_initDStream(&bitD3, istart3, length3); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|         errorCode = BIT_initDStream(&bitD4, istart4, length4); |  | ||||||
|         if (HUF_isError(errorCode)) return errorCode; |  | ||||||
|  |  | ||||||
|         /* 16-64 symbols per loop (4-16 symbols per stream) */ |  | ||||||
|         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); |  | ||||||
|         for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; ) |  | ||||||
|         { |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op4, &bitD4); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_1(op4, &bitD4); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_2(op4, &bitD4); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op1, &bitD1); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op2, &bitD2); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op3, &bitD3); |  | ||||||
|             HUF_DECODE_SYMBOLX6_0(op4, &bitD4); |  | ||||||
|  |  | ||||||
|             endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /* check corruption */ |  | ||||||
|         if (op1 > opStart2) return ERROR(corruption_detected); |  | ||||||
|         if (op2 > opStart3) return ERROR(corruption_detected); |  | ||||||
|         if (op3 > opStart4) return ERROR(corruption_detected); |  | ||||||
|         /* note : op4 supposed already verified within main loop */ |  | ||||||
|  |  | ||||||
|         /* finish bitStreams one by one */ |  | ||||||
|         HUF_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog); |  | ||||||
|         HUF_decodeStreamX6(op2, &bitD2, opStart3, DTable, dtLog); |  | ||||||
|         HUF_decodeStreamX6(op3, &bitD3, opStart4, DTable, dtLog); |  | ||||||
|         HUF_decodeStreamX6(op4, &bitD4, oend,     DTable, dtLog); |  | ||||||
|  |  | ||||||
|         /* check */ |  | ||||||
|         endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); |  | ||||||
|         if (!endSignal) return ERROR(corruption_detected); |  | ||||||
|  |  | ||||||
|         /* decoded size */ |  | ||||||
|         return dstSize; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) |  | ||||||
| { |  | ||||||
|     HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG); |  | ||||||
|     const BYTE* ip = (const BYTE*) cSrc; |  | ||||||
|  |  | ||||||
|     size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize); |  | ||||||
|     if (HUF_isError(hSize)) return hSize; |  | ||||||
|     if (hSize >= cSrcSize) return ERROR(srcSize_wrong); |  | ||||||
|     ip += hSize; |  | ||||||
|     cSrcSize -= hSize; |  | ||||||
|  |  | ||||||
|     return HUF_decompress4X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /**********************************/ | /**********************************/ | ||||||
| /* Generic decompression selector */ | /* Generic decompression selector */ | ||||||
| /**********************************/ | /**********************************/ | ||||||
| @@ -3173,7 +2820,7 @@ typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, | |||||||
|  |  | ||||||
| static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) | static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) | ||||||
| { | { | ||||||
|     static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, HUF_decompress4X6 }; |     static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL }; | ||||||
|     /* estimate decompression time */ |     /* estimate decompression time */ | ||||||
|     U32 Q; |     U32 Q; | ||||||
|     const U32 D256 = (U32)(dstSize >> 8); |     const U32 D256 = (U32)(dstSize >> 8); | ||||||
| @@ -3195,7 +2842,6 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_ | |||||||
|     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ |     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ | ||||||
|  |  | ||||||
|     if (Dtime[1] < Dtime[0]) algoNb = 1; |     if (Dtime[1] < Dtime[0]) algoNb = 1; | ||||||
|     if (Dtime[2] < Dtime[algoNb]) algoNb = 2; |  | ||||||
|  |  | ||||||
|     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); |     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2023,7 +2023,6 @@ extern "C" { | |||||||
| ******************************************/ | ******************************************/ | ||||||
| size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | ||||||
| size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */ | size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */ | ||||||
| size_t HUFv05_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbols decoder */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* **************************************** | /* **************************************** | ||||||
| @@ -2037,22 +2036,18 @@ HUFv05_decompress() does the following: | |||||||
| */ | */ | ||||||
| size_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize); | size_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize); | ||||||
| size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize); | size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize); | ||||||
| size_t HUFv05_readDTableX6 (unsigned* DTable, const void* src, size_t srcSize); |  | ||||||
|  |  | ||||||
| size_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); | size_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); | ||||||
| size_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); | size_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); | ||||||
| size_t HUFv05_decompress4X6_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* single stream variants */ | /* single stream variants */ | ||||||
|  |  | ||||||
| size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */ | ||||||
| size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */ | size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */ | ||||||
| size_t HUFv05_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbol decoder */ |  | ||||||
|  |  | ||||||
| size_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); | size_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); | ||||||
| size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); | size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); | ||||||
| size_t HUFv05_decompress1X6_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -2850,376 +2845,6 @@ size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* ********************************/ |  | ||||||
| /* quad-symbol decoding           */ |  | ||||||
| /* ********************************/ |  | ||||||
| typedef struct { BYTE nbBits; BYTE nbBytes; } HUFv05_DDescX6; |  | ||||||
| typedef union { BYTE byte[4]; U32 sequence; } HUFv05_DSeqX6; |  | ||||||
|  |  | ||||||
| /* recursive, up to level 3; may benefit from <template>-like strategy to nest each level inline */ |  | ||||||
| static void HUFv05_fillDTableX6LevelN(HUFv05_DDescX6* DDescription, HUFv05_DSeqX6* DSequence, int sizeLog, |  | ||||||
|                            const rankVal_t rankValOrigin, const U32 consumed, const int minWeight, const U32 maxWeight, |  | ||||||
|                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, const U32* rankStart, |  | ||||||
|                            const U32 nbBitsBaseline, HUFv05_DSeqX6 baseSeq, HUFv05_DDescX6 DDesc) |  | ||||||
| { |  | ||||||
|     const int scaleLog = nbBitsBaseline - sizeLog;   /* note : targetLog >= (nbBitsBaseline-1), hence scaleLog <= 1 */ |  | ||||||
|     const int minBits  = nbBitsBaseline - maxWeight; |  | ||||||
|     const U32 level = DDesc.nbBytes; |  | ||||||
|     U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1]; |  | ||||||
|     U32 symbolStartPos, s; |  | ||||||
|  |  | ||||||
|     /* local rankVal, will be modified */ |  | ||||||
|     memcpy(rankVal, rankValOrigin[consumed], sizeof(rankVal)); |  | ||||||
|  |  | ||||||
|     /* fill skipped values */ |  | ||||||
|     if (minWeight>1) { |  | ||||||
|         U32 i; |  | ||||||
|         const U32 skipSize = rankVal[minWeight]; |  | ||||||
|         for (i = 0; i < skipSize; i++) { |  | ||||||
|             DSequence[i] = baseSeq; |  | ||||||
|             DDescription[i] = DDesc; |  | ||||||
|     }   } |  | ||||||
|  |  | ||||||
|     /* fill DTable */ |  | ||||||
|     DDesc.nbBytes++; |  | ||||||
|     symbolStartPos = rankStart[minWeight]; |  | ||||||
|     for (s=symbolStartPos; s<sortedListSize; s++) { |  | ||||||
|         const BYTE symbol = sortedSymbols[s].symbol; |  | ||||||
|         const U32  weight = sortedSymbols[s].weight;   /* >= 1 (sorted) */ |  | ||||||
|         const int  nbBits = nbBitsBaseline - weight;   /* >= 1 (by construction) */ |  | ||||||
|         const int  totalBits = consumed+nbBits; |  | ||||||
|         const U32  start  = rankVal[weight]; |  | ||||||
|         const U32  length = 1 << (sizeLog-nbBits); |  | ||||||
|         baseSeq.byte[level] = symbol; |  | ||||||
|         DDesc.nbBits = (BYTE)totalBits; |  | ||||||
|  |  | ||||||
|         if ((level<3) && (sizeLog-totalBits >= minBits)) {  /* enough room for another symbol */ |  | ||||||
|             int nextMinWeight = totalBits + scaleLog; |  | ||||||
|             if (nextMinWeight < 1) nextMinWeight = 1; |  | ||||||
|             HUFv05_fillDTableX6LevelN(DDescription+start, DSequence+start, sizeLog-nbBits, |  | ||||||
|                            rankValOrigin, totalBits, nextMinWeight, maxWeight, |  | ||||||
|                            sortedSymbols, sortedListSize, rankStart, |  | ||||||
|                            nbBitsBaseline, baseSeq, DDesc);   /* recursive (max : level 3) */ |  | ||||||
|         } else { |  | ||||||
|             U32 i; |  | ||||||
|             const U32 end = start + length; |  | ||||||
|             for (i = start; i < end; i++) { |  | ||||||
|                 DDescription[i] = DDesc; |  | ||||||
|                 DSequence[i] = baseSeq; |  | ||||||
|         }   } |  | ||||||
|         rankVal[weight] += length; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* note : same preparation as X4 */ |  | ||||||
| size_t HUFv05_readDTableX6 (U32* DTable, const void* src, size_t srcSize) |  | ||||||
| { |  | ||||||
|     BYTE weightList[HUFv05_MAX_SYMBOL_VALUE + 1]; |  | ||||||
|     sortedSymbol_t sortedSymbol[HUFv05_MAX_SYMBOL_VALUE + 1]; |  | ||||||
|     U32 rankStats[HUFv05_ABSOLUTEMAX_TABLELOG + 1] = { 0 }; |  | ||||||
|     U32 rankStart0[HUFv05_ABSOLUTEMAX_TABLELOG + 2] = { 0 }; |  | ||||||
|     U32* const rankStart = rankStart0+1; |  | ||||||
|     U32 tableLog, maxW, sizeOfSort, nbSymbols; |  | ||||||
|     rankVal_t rankVal; |  | ||||||
|     const U32 memLog = DTable[0]; |  | ||||||
|     size_t iSize; |  | ||||||
|  |  | ||||||
|     if (memLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); |  | ||||||
|     //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */ |  | ||||||
|  |  | ||||||
|     iSize = HUFv05_readStats(weightList, HUFv05_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); |  | ||||||
|     if (HUFv05_isError(iSize)) return iSize; |  | ||||||
|  |  | ||||||
|     /* check result */ |  | ||||||
|     if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable is too small */ |  | ||||||
|  |  | ||||||
|     /* find maxWeight */ |  | ||||||
|     for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */ |  | ||||||
|  |  | ||||||
|     /* Get start index of each weight */ |  | ||||||
|     { |  | ||||||
|         U32 w, nextRankStart = 0; |  | ||||||
|         for (w=1; w<=maxW; w++) { |  | ||||||
|             U32 current = nextRankStart; |  | ||||||
|             nextRankStart += rankStats[w]; |  | ||||||
|             rankStart[w] = current; |  | ||||||
|         } |  | ||||||
|         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/ |  | ||||||
|         sizeOfSort = nextRankStart; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* sort symbols by weight */ |  | ||||||
|     { |  | ||||||
|         U32 s; |  | ||||||
|         for (s=0; s<nbSymbols; s++) { |  | ||||||
|             U32 w = weightList[s]; |  | ||||||
|             U32 r = rankStart[w]++; |  | ||||||
|             sortedSymbol[r].symbol = (BYTE)s; |  | ||||||
|             sortedSymbol[r].weight = (BYTE)w; |  | ||||||
|         } |  | ||||||
|         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Build rankVal */ |  | ||||||
|     { |  | ||||||
|         const U32 minBits = tableLog+1 - maxW; |  | ||||||
|         U32 nextRankVal = 0; |  | ||||||
|         U32 w, consumed; |  | ||||||
|         const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */ |  | ||||||
|         U32* rankVal0 = rankVal[0]; |  | ||||||
|         for (w=1; w<=maxW; w++) { |  | ||||||
|             U32 current = nextRankVal; |  | ||||||
|             nextRankVal += rankStats[w] << (w+rescale); |  | ||||||
|             rankVal0[w] = current; |  | ||||||
|         } |  | ||||||
|         for (consumed = minBits; consumed <= memLog - minBits; consumed++) { |  | ||||||
|             U32* rankValPtr = rankVal[consumed]; |  | ||||||
|             for (w = 1; w <= maxW; w++) { |  | ||||||
|                 rankValPtr[w] = rankVal0[w] >> consumed; |  | ||||||
|     }   }   } |  | ||||||
|  |  | ||||||
|     /* fill tables */ |  | ||||||
|     { |  | ||||||
|         void* ddPtr = DTable+1; |  | ||||||
|         HUFv05_DDescX6* DDescription = (HUFv05_DDescX6*)ddPtr; |  | ||||||
|         void* dsPtr = DTable + 1 + ((size_t)1<<(memLog-1)); |  | ||||||
|         HUFv05_DSeqX6* DSequence = (HUFv05_DSeqX6*)dsPtr; |  | ||||||
|         HUFv05_DSeqX6 DSeq; |  | ||||||
|         HUFv05_DDescX6 DDesc; |  | ||||||
|         DSeq.sequence = 0; |  | ||||||
|         DDesc.nbBits = 0; |  | ||||||
|         DDesc.nbBytes = 0; |  | ||||||
|         HUFv05_fillDTableX6LevelN(DDescription, DSequence, memLog, |  | ||||||
|                        (const U32 (*)[HUFv05_ABSOLUTEMAX_TABLELOG + 1])rankVal, 0, 1, maxW, |  | ||||||
|                        sortedSymbol, sizeOfSort, rankStart0, |  | ||||||
|                        tableLog+1, DSeq, DDesc); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return iSize; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static U32 HUFv05_decodeSymbolX6(void* op, BITv05_DStream_t* DStream, const HUFv05_DDescX6* dd, const HUFv05_DSeqX6* ds, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const size_t val = BITv05_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */ |  | ||||||
|     memcpy(op, ds+val, sizeof(HUFv05_DSeqX6)); |  | ||||||
|     BITv05_skipBits(DStream, dd[val].nbBits); |  | ||||||
|     return dd[val].nbBytes; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static U32 HUFv05_decodeLastSymbolsX6(void* op, const U32 maxL, BITv05_DStream_t* DStream, |  | ||||||
|                                   const HUFv05_DDescX6* dd, const HUFv05_DSeqX6* ds, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const size_t val = BITv05_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */ |  | ||||||
|     U32 length = dd[val].nbBytes; |  | ||||||
|     if (length <= maxL) { |  | ||||||
|         memcpy(op, ds+val, length); |  | ||||||
|         BITv05_skipBits(DStream, dd[val].nbBits); |  | ||||||
|         return length; |  | ||||||
|     } |  | ||||||
|     memcpy(op, ds+val, maxL); |  | ||||||
|     if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { |  | ||||||
|         BITv05_skipBits(DStream, dd[val].nbBits); |  | ||||||
|         if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) |  | ||||||
|             DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ |  | ||||||
|     } |  | ||||||
|     return maxL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define HUFv05_DECODE_SYMBOLX6_0(ptr, DStreamPtr) \ |  | ||||||
|     ptr += HUFv05_decodeSymbolX6(ptr, DStreamPtr, dd, ds, dtLog) |  | ||||||
|  |  | ||||||
| #define HUFv05_DECODE_SYMBOLX6_1(ptr, DStreamPtr) \ |  | ||||||
|     if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \ |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(ptr, DStreamPtr) |  | ||||||
|  |  | ||||||
| #define HUFv05_DECODE_SYMBOLX6_2(ptr, DStreamPtr) \ |  | ||||||
|     if (MEM_64bits()) \ |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(ptr, DStreamPtr) |  | ||||||
|  |  | ||||||
| static inline size_t HUFv05_decodeStreamX6(BYTE* p, BITv05_DStream_t* bitDPtr, BYTE* const pEnd, const U32* DTable, const U32 dtLog) |  | ||||||
| { |  | ||||||
|     const void* const ddPtr = DTable+1; |  | ||||||
|     const HUFv05_DDescX6* dd = (const HUFv05_DDescX6*)ddPtr; |  | ||||||
|     const void* const dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); |  | ||||||
|     const HUFv05_DSeqX6* ds = (const HUFv05_DSeqX6*)dsPtr; |  | ||||||
|     BYTE* const pStart = p; |  | ||||||
|  |  | ||||||
|     /* up to 16 symbols at a time */ |  | ||||||
|     while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-16)) { |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(p, bitDPtr); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_1(p, bitDPtr); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(p, bitDPtr); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(p, bitDPtr); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* closer to the end, up to 4 symbols at a time */ |  | ||||||
|     while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-4)) |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(p, bitDPtr); |  | ||||||
|  |  | ||||||
|     while ((BITv05_reloadDStream(bitDPtr) <= BITv05_DStream_endOfBuffer) && (p < pEnd)) |  | ||||||
|         p += HUFv05_decodeLastSymbolsX6(p, (U32)(pEnd-p), bitDPtr, dd, ds, dtLog); |  | ||||||
|  |  | ||||||
|     return p-pStart; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| size_t HUFv05_decompress1X6_usingDTable( |  | ||||||
|           void* dst,  size_t dstSize, |  | ||||||
|     const void* cSrc, size_t cSrcSize, |  | ||||||
|     const U32* DTable) |  | ||||||
| { |  | ||||||
|     const BYTE* const istart = (const BYTE*) cSrc; |  | ||||||
|     BYTE* const ostart = (BYTE*) dst; |  | ||||||
|     BYTE* const oend = ostart + dstSize; |  | ||||||
|  |  | ||||||
|     const U32 dtLog = DTable[0]; |  | ||||||
|     size_t errorCode; |  | ||||||
|  |  | ||||||
|     /* Init */ |  | ||||||
|     BITv05_DStream_t bitD; |  | ||||||
|     errorCode = BITv05_initDStream(&bitD, istart, cSrcSize); |  | ||||||
|     if (HUFv05_isError(errorCode)) return errorCode; |  | ||||||
|  |  | ||||||
|     /* finish bitStreams one by one */ |  | ||||||
|     HUFv05_decodeStreamX6(ostart, &bitD, oend, DTable, dtLog); |  | ||||||
|  |  | ||||||
|     /* check */ |  | ||||||
|     if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected); |  | ||||||
|  |  | ||||||
|     /* decoded size */ |  | ||||||
|     return dstSize; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t HUFv05_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) |  | ||||||
| { |  | ||||||
|     HUFv05_CREATE_STATIC_DTABLEX6(DTable, HUFv05_MAX_TABLELOG); |  | ||||||
|     const BYTE* ip = (const BYTE*) cSrc; |  | ||||||
|  |  | ||||||
|     size_t hSize = HUFv05_readDTableX6 (DTable, cSrc, cSrcSize); |  | ||||||
|     if (HUFv05_isError(hSize)) return hSize; |  | ||||||
|     if (hSize >= cSrcSize) return ERROR(srcSize_wrong); |  | ||||||
|     ip += hSize; |  | ||||||
|     cSrcSize -= hSize; |  | ||||||
|  |  | ||||||
|     return HUFv05_decompress1X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| size_t HUFv05_decompress4X6_usingDTable( |  | ||||||
|           void* dst,  size_t dstSize, |  | ||||||
|     const void* cSrc, size_t cSrcSize, |  | ||||||
|     const U32* DTable) |  | ||||||
| { |  | ||||||
|     const BYTE* const istart = (const BYTE*) cSrc; |  | ||||||
|     BYTE* const ostart = (BYTE*) dst; |  | ||||||
|     BYTE* const oend = ostart + dstSize; |  | ||||||
|  |  | ||||||
|     const U32 dtLog = DTable[0]; |  | ||||||
|     const void* const ddPtr = DTable+1; |  | ||||||
|     const HUFv05_DDescX6* dd = (const HUFv05_DDescX6*)ddPtr; |  | ||||||
|     const void* const dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); |  | ||||||
|     const HUFv05_DSeqX6* ds = (const HUFv05_DSeqX6*)dsPtr; |  | ||||||
|     size_t errorCode; |  | ||||||
|  |  | ||||||
|     /* Init */ |  | ||||||
|     BITv05_DStream_t bitD1; |  | ||||||
|     BITv05_DStream_t bitD2; |  | ||||||
|     BITv05_DStream_t bitD3; |  | ||||||
|     BITv05_DStream_t bitD4; |  | ||||||
|     const size_t length1 = MEM_readLE16(istart); |  | ||||||
|     const size_t length2 = MEM_readLE16(istart+2); |  | ||||||
|     const size_t length3 = MEM_readLE16(istart+4); |  | ||||||
|     size_t length4; |  | ||||||
|     const BYTE* const istart1 = istart + 6;  /* jumpTable */ |  | ||||||
|     const BYTE* const istart2 = istart1 + length1; |  | ||||||
|     const BYTE* const istart3 = istart2 + length2; |  | ||||||
|     const BYTE* const istart4 = istart3 + length3; |  | ||||||
|     const size_t segmentSize = (dstSize+3) / 4; |  | ||||||
|     BYTE* const opStart2 = ostart + segmentSize; |  | ||||||
|     BYTE* const opStart3 = opStart2 + segmentSize; |  | ||||||
|     BYTE* const opStart4 = opStart3 + segmentSize; |  | ||||||
|     BYTE* op1 = ostart; |  | ||||||
|     BYTE* op2 = opStart2; |  | ||||||
|     BYTE* op3 = opStart3; |  | ||||||
|     BYTE* op4 = opStart4; |  | ||||||
|     U32 endSignal; |  | ||||||
|  |  | ||||||
| 	/* Check */ |  | ||||||
|     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */ |  | ||||||
|  |  | ||||||
|     length4 = cSrcSize - (length1 + length2 + length3 + 6); |  | ||||||
|     if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */ |  | ||||||
|     errorCode = BITv05_initDStream(&bitD1, istart1, length1); |  | ||||||
|     if (HUFv05_isError(errorCode)) return errorCode; |  | ||||||
|     errorCode = BITv05_initDStream(&bitD2, istart2, length2); |  | ||||||
|     if (HUFv05_isError(errorCode)) return errorCode; |  | ||||||
|     errorCode = BITv05_initDStream(&bitD3, istart3, length3); |  | ||||||
|     if (HUFv05_isError(errorCode)) return errorCode; |  | ||||||
|     errorCode = BITv05_initDStream(&bitD4, istart4, length4); |  | ||||||
|     if (HUFv05_isError(errorCode)) return errorCode; |  | ||||||
|  |  | ||||||
|     /* 16-64 symbols per loop (4-16 symbols per stream) */ |  | ||||||
|     endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4); |  | ||||||
|     for ( ; (op3 <= opStart4) && (endSignal==BITv05_DStream_unfinished) && (op4<=(oend-16)) ; ) { |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op1, &bitD1); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op2, &bitD2); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op3, &bitD3); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op4, &bitD4); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_1(op1, &bitD1); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_1(op2, &bitD2); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_1(op3, &bitD3); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_1(op4, &bitD4); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op1, &bitD1); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op2, &bitD2); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op3, &bitD3); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_2(op4, &bitD4); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(op1, &bitD1); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(op2, &bitD2); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(op3, &bitD3); |  | ||||||
|         HUFv05_DECODE_SYMBOLX6_0(op4, &bitD4); |  | ||||||
|  |  | ||||||
|         endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* check corruption */ |  | ||||||
|     if (op1 > opStart2) return ERROR(corruption_detected); |  | ||||||
|     if (op2 > opStart3) return ERROR(corruption_detected); |  | ||||||
|     if (op3 > opStart4) return ERROR(corruption_detected); |  | ||||||
|     /* note : op4 supposed already verified within main loop */ |  | ||||||
|  |  | ||||||
|     /* finish bitStreams one by one */ |  | ||||||
|     HUFv05_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog); |  | ||||||
|     HUFv05_decodeStreamX6(op2, &bitD2, opStart3, DTable, dtLog); |  | ||||||
|     HUFv05_decodeStreamX6(op3, &bitD3, opStart4, DTable, dtLog); |  | ||||||
|     HUFv05_decodeStreamX6(op4, &bitD4, oend,     DTable, dtLog); |  | ||||||
|  |  | ||||||
|     /* check */ |  | ||||||
|     endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4); |  | ||||||
|     if (!endSignal) return ERROR(corruption_detected); |  | ||||||
|  |  | ||||||
|     /* decoded size */ |  | ||||||
|     return dstSize; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| size_t HUFv05_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) |  | ||||||
| { |  | ||||||
|     HUFv05_CREATE_STATIC_DTABLEX6(DTable, HUFv05_MAX_TABLELOG); |  | ||||||
|     const BYTE* ip = (const BYTE*) cSrc; |  | ||||||
|  |  | ||||||
|     size_t hSize = HUFv05_readDTableX6 (DTable, cSrc, cSrcSize); |  | ||||||
|     if (HUFv05_isError(hSize)) return hSize; |  | ||||||
|     if (hSize >= cSrcSize) return ERROR(srcSize_wrong); |  | ||||||
|     ip += hSize; |  | ||||||
|     cSrcSize -= hSize; |  | ||||||
|  |  | ||||||
|     return HUFv05_decompress4X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* ********************************/ | /* ********************************/ | ||||||
| /* Generic decompression selector */ | /* Generic decompression selector */ | ||||||
| /* ********************************/ | /* ********************************/ | ||||||
| @@ -3250,7 +2875,7 @@ typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, | |||||||
|  |  | ||||||
| size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) | size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) | ||||||
| { | { | ||||||
|     static const decompressionAlgo decompress[3] = { HUFv05_decompress4X2, HUFv05_decompress4X4, HUFv05_decompress4X6 }; |     static const decompressionAlgo decompress[3] = { HUFv05_decompress4X2, HUFv05_decompress4X4, NULL }; | ||||||
|     /* estimate decompression time */ |     /* estimate decompression time */ | ||||||
|     U32 Q; |     U32 Q; | ||||||
|     const U32 D256 = (U32)(dstSize >> 8); |     const U32 D256 = (U32)(dstSize >> 8); | ||||||
| @@ -3272,7 +2897,6 @@ size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS | |||||||
|     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ |     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ | ||||||
|  |  | ||||||
|     if (Dtime[1] < Dtime[0]) algoNb = 1; |     if (Dtime[1] < Dtime[0]) algoNb = 1; | ||||||
|     if (Dtime[2] < Dtime[algoNb]) algoNb = 2; |  | ||||||
|  |  | ||||||
|     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); |     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); | ||||||
|  |  | ||||||
| @@ -4706,8 +4330,7 @@ size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDst | |||||||
|     *srcSizePtr = ip-istart; |     *srcSizePtr = ip-istart; | ||||||
|     *maxDstSizePtr = op-ostart; |     *maxDstSizePtr = op-ostart; | ||||||
|  |  | ||||||
|     { |     {   size_t nextSrcSizeHint = ZSTDv05_nextSrcSizeToDecompress(zbc->zc); | ||||||
|         size_t nextSrcSizeHint = ZSTDv05_nextSrcSizeToDecompress(zbc->zc); |  | ||||||
|         if (nextSrcSizeHint > ZBUFFv05_blockHeaderSize) nextSrcSizeHint+= ZBUFFv05_blockHeaderSize;   /* get next block header too */ |         if (nextSrcSizeHint > ZBUFFv05_blockHeaderSize) nextSrcSizeHint+= ZBUFFv05_blockHeaderSize;   /* get next block header too */ | ||||||
|         nextSrcSizeHint -= zbc->inPos;   /* already loaded*/ |         nextSrcSizeHint -= zbc->inPos;   /* already loaded*/ | ||||||
|         return nextSrcSizeHint; |         return nextSrcSizeHint; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user