1 /* ******************************************************************
2    huff0 huffman decoder,
3    part of Finite State Entropy library
4    Copyright (C) 2013-present, Yann Collet.
5 
6    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7 
8    Redistribution and use in source and binary forms, with or without
9    modification, are permitted provided that the following conditions are
10    met:
11 
12        * Redistributions of source code must retain the above copyright
13    notice, this list of conditions and the following disclaimer.
14        * Redistributions in binary form must reproduce the above
15    copyright notice, this list of conditions and the following disclaimer
16    in the documentation and/or other materials provided with the
17    distribution.
18 
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31     You can contact the author at :
32     - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
33 ****************************************************************** */
34 
35 /* **************************************************************
36 *  Dependencies
37 ****************************************************************/
38 #include <string.h>     /* memcpy, memset */
39 #include "compiler.h"
40 #include "bitstream.h"  /* BIT_* */
41 #include "fse.h"        /* to compress headers */
42 #define HUF_STATIC_LINKING_ONLY
43 #include "huf.h"
44 #include "error_private.h"
45 
46 
47 /* **************************************************************
48 *  Error Management
49 ****************************************************************/
50 #define HUF_isError ERR_isError
51 #define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; }
52 
53 
54 /* **************************************************************
55 *  Byte alignment for workSpace management
56 ****************************************************************/
57 #define HUF_ALIGN(x, a)         HUF_ALIGN_MASK((x), (a) - 1)
58 #define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
59 
60 
61 /*-***************************/
62 /*  generic DTableDesc       */
63 /*-***************************/
64 typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
65 
HUF_getDTableDesc(const HUF_DTable * table)66 static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
67 {
68     DTableDesc dtd;
69     memcpy(&dtd, table, sizeof(dtd));
70     return dtd;
71 }
72 
73 
74 /*-***************************/
75 /*  single-symbol decoding   */
76 /*-***************************/
77 typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1;   /* single-symbol decoding */
78 
HUF_readDTableX1_wksp(HUF_DTable * DTable,const void * src,size_t srcSize,void * workSpace,size_t wkspSize)79 size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
80 {
81     U32 tableLog = 0;
82     U32 nbSymbols = 0;
83     size_t iSize;
84     void* const dtPtr = DTable + 1;
85     HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
86 
87     U32* rankVal;
88     BYTE* huffWeight;
89     size_t spaceUsed32 = 0;
90 
91     rankVal = (U32 *)workSpace + spaceUsed32;
92     spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;
93     huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32);
94     spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
95 
96     if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
97 
98     DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
99     /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */
100 
101     iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
102     if (HUF_isError(iSize)) return iSize;
103 
104     /* Table header */
105     {   DTableDesc dtd = HUF_getDTableDesc(DTable);
106         if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */
107         dtd.tableType = 0;
108         dtd.tableLog = (BYTE)tableLog;
109         memcpy(DTable, &dtd, sizeof(dtd));
110     }
111 
112     /* Calculate starting value for each rank */
113     {   U32 n, nextRankStart = 0;
114         for (n=1; n<tableLog+1; n++) {
115             U32 const current = nextRankStart;
116             nextRankStart += (rankVal[n] << (n-1));
117             rankVal[n] = current;
118     }   }
119 
120     /* fill DTable */
121     {   U32 n;
122         for (n=0; n<nbSymbols; n++) {
123             U32 const w = huffWeight[n];
124             U32 const length = (1 << w) >> 1;
125             U32 u;
126             HUF_DEltX1 D;
127             D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
128             for (u = rankVal[w]; u < rankVal[w] + length; u++)
129                 dt[u] = D;
130             rankVal[w] += length;
131     }   }
132 
133     return iSize;
134 }
135 
HUF_readDTableX1(HUF_DTable * DTable,const void * src,size_t srcSize)136 size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize)
137 {
138     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
139     return HUF_readDTableX1_wksp(DTable, src, srcSize,
140                                  workSpace, sizeof(workSpace));
141 }
142 
143 FORCE_INLINE_TEMPLATE BYTE
HUF_decodeSymbolX1(BIT_DStream_t * Dstream,const HUF_DEltX1 * dt,const U32 dtLog)144 HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
145 {
146     size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
147     BYTE const c = dt[val].byte;
148     BIT_skipBits(Dstream, dt[val].nbBits);
149     return c;
150 }
151 
152 #define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
153     *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog)
154 
155 #define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)  \
156     if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
157         HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
158 
159 #define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \
160     if (MEM_64bits()) \
161         HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
162 
163 HINT_INLINE size_t
HUF_decodeStreamX1(BYTE * p,BIT_DStream_t * const bitDPtr,BYTE * const pEnd,const HUF_DEltX1 * const dt,const U32 dtLog)164 HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)
165 {
166     BYTE* const pStart = p;
167 
168     /* up to 4 symbols at a time */
169     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
170         HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
171         HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
172         HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
173         HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
174     }
175 
176     /* [0-3] symbols remaining */
177     if (MEM_32bits())
178         while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))
179             HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
180 
181     /* no more data to retrieve from bitstream, no need to reload */
182     while (p < pEnd)
183         HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
184 
185     return pEnd-pStart;
186 }
187 
188 FORCE_INLINE_TEMPLATE size_t
HUF_decompress1X1_usingDTable_internal_body(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)189 HUF_decompress1X1_usingDTable_internal_body(
190           void* dst,  size_t dstSize,
191     const void* cSrc, size_t cSrcSize,
192     const HUF_DTable* DTable)
193 {
194     BYTE* op = (BYTE*)dst;
195     BYTE* const oend = op + dstSize;
196     const void* dtPtr = DTable + 1;
197     const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
198     BIT_DStream_t bitD;
199     DTableDesc const dtd = HUF_getDTableDesc(DTable);
200     U32 const dtLog = dtd.tableLog;
201 
202     CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
203 
204     HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);
205 
206     if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
207 
208     return dstSize;
209 }
210 
211 FORCE_INLINE_TEMPLATE size_t
HUF_decompress4X1_usingDTable_internal_body(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)212 HUF_decompress4X1_usingDTable_internal_body(
213           void* dst,  size_t dstSize,
214     const void* cSrc, size_t cSrcSize,
215     const HUF_DTable* DTable)
216 {
217     /* Check */
218     if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */
219 
220     {   const BYTE* const istart = (const BYTE*) cSrc;
221         BYTE* const ostart = (BYTE*) dst;
222         BYTE* const oend = ostart + dstSize;
223         const void* const dtPtr = DTable + 1;
224         const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
225 
226         /* Init */
227         BIT_DStream_t bitD1;
228         BIT_DStream_t bitD2;
229         BIT_DStream_t bitD3;
230         BIT_DStream_t bitD4;
231         size_t const length1 = MEM_readLE16(istart);
232         size_t const length2 = MEM_readLE16(istart+2);
233         size_t const length3 = MEM_readLE16(istart+4);
234         size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
235         const BYTE* const istart1 = istart + 6;  /* jumpTable */
236         const BYTE* const istart2 = istart1 + length1;
237         const BYTE* const istart3 = istart2 + length2;
238         const BYTE* const istart4 = istart3 + length3;
239         const size_t segmentSize = (dstSize+3) / 4;
240         BYTE* const opStart2 = ostart + segmentSize;
241         BYTE* const opStart3 = opStart2 + segmentSize;
242         BYTE* const opStart4 = opStart3 + segmentSize;
243         BYTE* op1 = ostart;
244         BYTE* op2 = opStart2;
245         BYTE* op3 = opStart3;
246         BYTE* op4 = opStart4;
247         U32 endSignal = BIT_DStream_unfinished;
248         DTableDesc const dtd = HUF_getDTableDesc(DTable);
249         U32 const dtLog = dtd.tableLog;
250 
251         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
252         CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
253         CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
254         CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
255         CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
256 
257         /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
258         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
259         while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) {
260             HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
261             HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
262             HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
263             HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
264             HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
265             HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
266             HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
267             HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
268             HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
269             HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
270             HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
271             HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
272             HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
273             HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
274             HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
275             HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
276             BIT_reloadDStream(&bitD1);
277             BIT_reloadDStream(&bitD2);
278             BIT_reloadDStream(&bitD3);
279             BIT_reloadDStream(&bitD4);
280         }
281 
282         /* check corruption */
283         /* note : should not be necessary : op# advance in lock step, and we control op4.
284          *        but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */
285         if (op1 > opStart2) return ERROR(corruption_detected);
286         if (op2 > opStart3) return ERROR(corruption_detected);
287         if (op3 > opStart4) return ERROR(corruption_detected);
288         /* note : op4 supposed already verified within main loop */
289 
290         /* finish bitStreams one by one */
291         HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);
292         HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);
293         HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);
294         HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);
295 
296         /* check */
297         { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
298           if (!endCheck) return ERROR(corruption_detected); }
299 
300         /* decoded size */
301         return dstSize;
302     }
303 }
304 
305 
306 typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
307                                                const void *cSrc,
308                                                size_t cSrcSize,
309                                                const HUF_DTable *DTable);
310 #if DYNAMIC_BMI2
311 
312 #define HUF_DGEN(fn)                                                               \
313                                                                             \
314     static size_t fn##_default(                                             \
315                   void* dst,  size_t dstSize,                               \
316             const void* cSrc, size_t cSrcSize,                              \
317             const HUF_DTable* DTable)                                       \
318     {                                                                       \
319         return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
320     }                                                                       \
321                                                                             \
322     static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2(                       \
323                   void* dst,  size_t dstSize,                               \
324             const void* cSrc, size_t cSrcSize,                              \
325             const HUF_DTable* DTable)                                       \
326     {                                                                       \
327         return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
328     }                                                                       \
329                                                                             \
330     static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \
331                      size_t cSrcSize, HUF_DTable const* DTable, int bmi2)   \
332     {                                                                       \
333         if (bmi2) {                                                         \
334             return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
335         }                                                                   \
336         return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
337     }
338 
339 #else
340 
341 #define HUF_DGEN(fn)                                                               \
342     static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \
343                      size_t cSrcSize, HUF_DTable const* DTable, int bmi2)   \
344     {                                                                       \
345         (void)bmi2;                                                         \
346         return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
347     }
348 
349 #endif
350 
351 HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
HUF_DGEN(HUF_decompress4X1_usingDTable_internal)352 HUF_DGEN(HUF_decompress4X1_usingDTable_internal)
353 
354 
355 
356 size_t HUF_decompress1X1_usingDTable(
357           void* dst,  size_t dstSize,
358     const void* cSrc, size_t cSrcSize,
359     const HUF_DTable* DTable)
360 {
361     DTableDesc dtd = HUF_getDTableDesc(DTable);
362     if (dtd.tableType != 0) return ERROR(GENERIC);
363     return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
364 }
365 
HUF_decompress1X1_DCtx_wksp(HUF_DTable * DCtx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize)366 size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
367                                    const void* cSrc, size_t cSrcSize,
368                                    void* workSpace, size_t wkspSize)
369 {
370     const BYTE* ip = (const BYTE*) cSrc;
371 
372     size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
373     if (HUF_isError(hSize)) return hSize;
374     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
375     ip += hSize; cSrcSize -= hSize;
376 
377     return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
378 }
379 
380 
HUF_decompress1X1_DCtx(HUF_DTable * DCtx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)381 size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
382                               const void* cSrc, size_t cSrcSize)
383 {
384     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
385     return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
386                                        workSpace, sizeof(workSpace));
387 }
388 
HUF_decompress1X1(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)389 size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
390 {
391     HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
392     return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
393 }
394 
HUF_decompress4X1_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)395 size_t HUF_decompress4X1_usingDTable(
396           void* dst,  size_t dstSize,
397     const void* cSrc, size_t cSrcSize,
398     const HUF_DTable* DTable)
399 {
400     DTableDesc dtd = HUF_getDTableDesc(DTable);
401     if (dtd.tableType != 0) return ERROR(GENERIC);
402     return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
403 }
404 
HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize,int bmi2)405 static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
406                                    const void* cSrc, size_t cSrcSize,
407                                    void* workSpace, size_t wkspSize, int bmi2)
408 {
409     const BYTE* ip = (const BYTE*) cSrc;
410 
411     size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize,
412                                                 workSpace, wkspSize);
413     if (HUF_isError(hSize)) return hSize;
414     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
415     ip += hSize; cSrcSize -= hSize;
416 
417     return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
418 }
419 
HUF_decompress4X1_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize)420 size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
421                                    const void* cSrc, size_t cSrcSize,
422                                    void* workSpace, size_t wkspSize)
423 {
424     return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
425 }
426 
427 
HUF_decompress4X1_DCtx(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)428 size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
429 {
430     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
431     return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
432                                        workSpace, sizeof(workSpace));
433 }
HUF_decompress4X1(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)434 size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
435 {
436     HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
437     return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
438 }
439 
440 
441 /* *************************/
442 /* double-symbols decoding */
443 /* *************************/
444 
445 typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2;  /* double-symbols decoding */
446 typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
447 typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
448 typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
449 
450 
451 /* HUF_fillDTableX2Level2() :
452  * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
HUF_fillDTableX2Level2(HUF_DEltX2 * DTable,U32 sizeLog,const U32 consumed,const U32 * rankValOrigin,const int minWeight,const sortedSymbol_t * sortedSymbols,const U32 sortedListSize,U32 nbBitsBaseline,U16 baseSeq)453 static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
454                            const U32* rankValOrigin, const int minWeight,
455                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
456                            U32 nbBitsBaseline, U16 baseSeq)
457 {
458     HUF_DEltX2 DElt;
459     U32 rankVal[HUF_TABLELOG_MAX + 1];
460 
461     /* get pre-calculated rankVal */
462     memcpy(rankVal, rankValOrigin, sizeof(rankVal));
463 
464     /* fill skipped values */
465     if (minWeight>1) {
466         U32 i, skipSize = rankVal[minWeight];
467         MEM_writeLE16(&(DElt.sequence), baseSeq);
468         DElt.nbBits   = (BYTE)(consumed);
469         DElt.length   = 1;
470         for (i = 0; i < skipSize; i++)
471             DTable[i] = DElt;
472     }
473 
474     /* fill DTable */
475     {   U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */
476             const U32 symbol = sortedSymbols[s].symbol;
477             const U32 weight = sortedSymbols[s].weight;
478             const U32 nbBits = nbBitsBaseline - weight;
479             const U32 length = 1 << (sizeLog-nbBits);
480             const U32 start = rankVal[weight];
481             U32 i = start;
482             const U32 end = start + length;
483 
484             MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
485             DElt.nbBits = (BYTE)(nbBits + consumed);
486             DElt.length = 2;
487             do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */
488 
489             rankVal[weight] += length;
490     }   }
491 }
492 
493 
HUF_fillDTableX2(HUF_DEltX2 * DTable,const U32 targetLog,const sortedSymbol_t * sortedList,const U32 sortedListSize,const U32 * rankStart,rankVal_t rankValOrigin,const U32 maxWeight,const U32 nbBitsBaseline)494 static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
495                            const sortedSymbol_t* sortedList, const U32 sortedListSize,
496                            const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
497                            const U32 nbBitsBaseline)
498 {
499     U32 rankVal[HUF_TABLELOG_MAX + 1];
500     const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */
501     const U32 minBits  = nbBitsBaseline - maxWeight;
502     U32 s;
503 
504     memcpy(rankVal, rankValOrigin, sizeof(rankVal));
505 
506     /* fill DTable */
507     for (s=0; s<sortedListSize; s++) {
508         const U16 symbol = sortedList[s].symbol;
509         const U32 weight = sortedList[s].weight;
510         const U32 nbBits = nbBitsBaseline - weight;
511         const U32 start = rankVal[weight];
512         const U32 length = 1 << (targetLog-nbBits);
513 
514         if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */
515             U32 sortedRank;
516             int minWeight = nbBits + scaleLog;
517             if (minWeight < 1) minWeight = 1;
518             sortedRank = rankStart[minWeight];
519             HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
520                            rankValOrigin[nbBits], minWeight,
521                            sortedList+sortedRank, sortedListSize-sortedRank,
522                            nbBitsBaseline, symbol);
523         } else {
524             HUF_DEltX2 DElt;
525             MEM_writeLE16(&(DElt.sequence), symbol);
526             DElt.nbBits = (BYTE)(nbBits);
527             DElt.length = 1;
528             {   U32 const end = start + length;
529                 U32 u;
530                 for (u = start; u < end; u++) DTable[u] = DElt;
531         }   }
532         rankVal[weight] += length;
533     }
534 }
535 
HUF_readDTableX2_wksp(HUF_DTable * DTable,const void * src,size_t srcSize,void * workSpace,size_t wkspSize)536 size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src,
537                              size_t srcSize, void* workSpace,
538                              size_t wkspSize)
539 {
540     U32 tableLog, maxW, sizeOfSort, nbSymbols;
541     DTableDesc dtd = HUF_getDTableDesc(DTable);
542     U32 const maxTableLog = dtd.maxTableLog;
543     size_t iSize;
544     void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */
545     HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
546     U32 *rankStart;
547 
548     rankValCol_t* rankVal;
549     U32* rankStats;
550     U32* rankStart0;
551     sortedSymbol_t* sortedSymbol;
552     BYTE* weightList;
553     size_t spaceUsed32 = 0;
554 
555     rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32);
556     spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
557     rankStats = (U32 *)workSpace + spaceUsed32;
558     spaceUsed32 += HUF_TABLELOG_MAX + 1;
559     rankStart0 = (U32 *)workSpace + spaceUsed32;
560     spaceUsed32 += HUF_TABLELOG_MAX + 2;
561     sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t);
562     spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
563     weightList = (BYTE *)((U32 *)workSpace + spaceUsed32);
564     spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
565 
566     if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
567 
568     rankStart = rankStart0 + 1;
569     memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
570 
571     DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */
572     if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
573     /* memset(weightList, 0, sizeof(weightList)); */  /* is not necessary, even though some analyzer complain ... */
574 
575     iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
576     if (HUF_isError(iSize)) return iSize;
577 
578     /* check result */
579     if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */
580 
581     /* find maxWeight */
582     for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */
583 
584     /* Get start index of each weight */
585     {   U32 w, nextRankStart = 0;
586         for (w=1; w<maxW+1; w++) {
587             U32 current = nextRankStart;
588             nextRankStart += rankStats[w];
589             rankStart[w] = current;
590         }
591         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
592         sizeOfSort = nextRankStart;
593     }
594 
595     /* sort symbols by weight */
596     {   U32 s;
597         for (s=0; s<nbSymbols; s++) {
598             U32 const w = weightList[s];
599             U32 const r = rankStart[w]++;
600             sortedSymbol[r].symbol = (BYTE)s;
601             sortedSymbol[r].weight = (BYTE)w;
602         }
603         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
604     }
605 
606     /* Build rankVal */
607     {   U32* const rankVal0 = rankVal[0];
608         {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */
609             U32 nextRankVal = 0;
610             U32 w;
611             for (w=1; w<maxW+1; w++) {
612                 U32 current = nextRankVal;
613                 nextRankVal += rankStats[w] << (w+rescale);
614                 rankVal0[w] = current;
615         }   }
616         {   U32 const minBits = tableLog+1 - maxW;
617             U32 consumed;
618             for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
619                 U32* const rankValPtr = rankVal[consumed];
620                 U32 w;
621                 for (w = 1; w < maxW+1; w++) {
622                     rankValPtr[w] = rankVal0[w] >> consumed;
623     }   }   }   }
624 
625     HUF_fillDTableX2(dt, maxTableLog,
626                    sortedSymbol, sizeOfSort,
627                    rankStart0, rankVal, maxW,
628                    tableLog+1);
629 
630     dtd.tableLog = (BYTE)maxTableLog;
631     dtd.tableType = 1;
632     memcpy(DTable, &dtd, sizeof(dtd));
633     return iSize;
634 }
635 
HUF_readDTableX2(HUF_DTable * DTable,const void * src,size_t srcSize)636 size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
637 {
638   U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
639   return HUF_readDTableX2_wksp(DTable, src, srcSize,
640                                workSpace, sizeof(workSpace));
641 }
642 
643 
644 FORCE_INLINE_TEMPLATE U32
HUF_decodeSymbolX2(void * op,BIT_DStream_t * DStream,const HUF_DEltX2 * dt,const U32 dtLog)645 HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
646 {
647     size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
648     memcpy(op, dt+val, 2);
649     BIT_skipBits(DStream, dt[val].nbBits);
650     return dt[val].length;
651 }
652 
653 FORCE_INLINE_TEMPLATE U32
HUF_decodeLastSymbolX2(void * op,BIT_DStream_t * DStream,const HUF_DEltX2 * dt,const U32 dtLog)654 HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
655 {
656     size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
657     memcpy(op, dt+val, 1);
658     if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
659     else {
660         if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
661             BIT_skipBits(DStream, dt[val].nbBits);
662             if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
663                 /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
664                 DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
665     }   }
666     return 1;
667 }
668 
669 #define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
670     ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
671 
672 #define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
673     if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
674         ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
675 
676 #define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
677     if (MEM_64bits()) \
678         ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
679 
680 HINT_INLINE size_t
HUF_decodeStreamX2(BYTE * p,BIT_DStream_t * bitDPtr,BYTE * const pEnd,const HUF_DEltX2 * const dt,const U32 dtLog)681 HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
682                 const HUF_DEltX2* const dt, const U32 dtLog)
683 {
684     BYTE* const pStart = p;
685 
686     /* up to 8 symbols at a time */
687     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
688         HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
689         HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
690         HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
691         HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
692     }
693 
694     /* closer to end : up to 2 symbols at a time */
695     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
696         HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
697 
698     while (p <= pEnd-2)
699         HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
700 
701     if (p < pEnd)
702         p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
703 
704     return p-pStart;
705 }
706 
707 FORCE_INLINE_TEMPLATE size_t
HUF_decompress1X2_usingDTable_internal_body(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)708 HUF_decompress1X2_usingDTable_internal_body(
709           void* dst,  size_t dstSize,
710     const void* cSrc, size_t cSrcSize,
711     const HUF_DTable* DTable)
712 {
713     BIT_DStream_t bitD;
714 
715     /* Init */
716     CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
717 
718     /* decode */
719     {   BYTE* const ostart = (BYTE*) dst;
720         BYTE* const oend = ostart + dstSize;
721         const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */
722         const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
723         DTableDesc const dtd = HUF_getDTableDesc(DTable);
724         HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);
725     }
726 
727     /* check */
728     if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
729 
730     /* decoded size */
731     return dstSize;
732 }
733 
734 
735 FORCE_INLINE_TEMPLATE size_t
HUF_decompress4X2_usingDTable_internal_body(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)736 HUF_decompress4X2_usingDTable_internal_body(
737           void* dst,  size_t dstSize,
738     const void* cSrc, size_t cSrcSize,
739     const HUF_DTable* DTable)
740 {
741     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
742 
743     {   const BYTE* const istart = (const BYTE*) cSrc;
744         BYTE* const ostart = (BYTE*) dst;
745         BYTE* const oend = ostart + dstSize;
746         const void* const dtPtr = DTable+1;
747         const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
748 
749         /* Init */
750         BIT_DStream_t bitD1;
751         BIT_DStream_t bitD2;
752         BIT_DStream_t bitD3;
753         BIT_DStream_t bitD4;
754         size_t const length1 = MEM_readLE16(istart);
755         size_t const length2 = MEM_readLE16(istart+2);
756         size_t const length3 = MEM_readLE16(istart+4);
757         size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
758         const BYTE* const istart1 = istart + 6;  /* jumpTable */
759         const BYTE* const istart2 = istart1 + length1;
760         const BYTE* const istart3 = istart2 + length2;
761         const BYTE* const istart4 = istart3 + length3;
762         size_t const segmentSize = (dstSize+3) / 4;
763         BYTE* const opStart2 = ostart + segmentSize;
764         BYTE* const opStart3 = opStart2 + segmentSize;
765         BYTE* const opStart4 = opStart3 + segmentSize;
766         BYTE* op1 = ostart;
767         BYTE* op2 = opStart2;
768         BYTE* op3 = opStart3;
769         BYTE* op4 = opStart4;
770         U32 endSignal;
771         DTableDesc const dtd = HUF_getDTableDesc(DTable);
772         U32 const dtLog = dtd.tableLog;
773 
774         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
775         CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
776         CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
777         CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
778         CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
779 
780         /* 16-32 symbols per loop (4-8 symbols per stream) */
781         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
782         for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
783             HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
784             HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
785             HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
786             HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
787             HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
788             HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
789             HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
790             HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
791             HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
792             HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
793             HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
794             HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
795             HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
796             HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
797             HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
798             HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
799 
800             endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
801         }
802 
803         /* check corruption */
804         if (op1 > opStart2) return ERROR(corruption_detected);
805         if (op2 > opStart3) return ERROR(corruption_detected);
806         if (op3 > opStart4) return ERROR(corruption_detected);
807         /* note : op4 already verified within main loop */
808 
809         /* finish bitStreams one by one */
810         HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
811         HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
812         HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
813         HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);
814 
815         /* check */
816         { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
817           if (!endCheck) return ERROR(corruption_detected); }
818 
819         /* decoded size */
820         return dstSize;
821     }
822 }
823 
824 HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
HUF_DGEN(HUF_decompress4X2_usingDTable_internal)825 HUF_DGEN(HUF_decompress4X2_usingDTable_internal)
826 
827 size_t HUF_decompress1X2_usingDTable(
828           void* dst,  size_t dstSize,
829     const void* cSrc, size_t cSrcSize,
830     const HUF_DTable* DTable)
831 {
832     DTableDesc dtd = HUF_getDTableDesc(DTable);
833     if (dtd.tableType != 1) return ERROR(GENERIC);
834     return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
835 }
836 
HUF_decompress1X2_DCtx_wksp(HUF_DTable * DCtx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize)837 size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
838                                    const void* cSrc, size_t cSrcSize,
839                                    void* workSpace, size_t wkspSize)
840 {
841     const BYTE* ip = (const BYTE*) cSrc;
842 
843     size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
844                                                workSpace, wkspSize);
845     if (HUF_isError(hSize)) return hSize;
846     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
847     ip += hSize; cSrcSize -= hSize;
848 
849     return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
850 }
851 
852 
HUF_decompress1X2_DCtx(HUF_DTable * DCtx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)853 size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
854                               const void* cSrc, size_t cSrcSize)
855 {
856     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
857     return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
858                                        workSpace, sizeof(workSpace));
859 }
860 
HUF_decompress1X2(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)861 size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
862 {
863     HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
864     return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
865 }
866 
HUF_decompress4X2_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)867 size_t HUF_decompress4X2_usingDTable(
868           void* dst,  size_t dstSize,
869     const void* cSrc, size_t cSrcSize,
870     const HUF_DTable* DTable)
871 {
872     DTableDesc dtd = HUF_getDTableDesc(DTable);
873     if (dtd.tableType != 1) return ERROR(GENERIC);
874     return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
875 }
876 
HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize,int bmi2)877 static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
878                                    const void* cSrc, size_t cSrcSize,
879                                    void* workSpace, size_t wkspSize, int bmi2)
880 {
881     const BYTE* ip = (const BYTE*) cSrc;
882 
883     size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
884                                          workSpace, wkspSize);
885     if (HUF_isError(hSize)) return hSize;
886     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
887     ip += hSize; cSrcSize -= hSize;
888 
889     return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
890 }
891 
HUF_decompress4X2_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize)892 size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
893                                    const void* cSrc, size_t cSrcSize,
894                                    void* workSpace, size_t wkspSize)
895 {
896     return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
897 }
898 
899 
HUF_decompress4X2_DCtx(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)900 size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
901                               const void* cSrc, size_t cSrcSize)
902 {
903     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
904     return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
905                                        workSpace, sizeof(workSpace));
906 }
907 
HUF_decompress4X2(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)908 size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
909 {
910     HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
911     return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
912 }
913 
914 
915 /* ***********************************/
916 /* Universal decompression selectors */
917 /* ***********************************/
918 
HUF_decompress1X_usingDTable(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)919 size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
920                                     const void* cSrc, size_t cSrcSize,
921                                     const HUF_DTable* DTable)
922 {
923     DTableDesc const dtd = HUF_getDTableDesc(DTable);
924     return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
925                            HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
926 }
927 
HUF_decompress4X_usingDTable(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)928 size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
929                                     const void* cSrc, size_t cSrcSize,
930                                     const HUF_DTable* DTable)
931 {
932     DTableDesc const dtd = HUF_getDTableDesc(DTable);
933     return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
934                            HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
935 }
936 
937 
938 typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
939 static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
940 {
941     /* single, double, quad */
942     {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */
943     {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */
944     {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */
945     {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */
946     {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */
947     {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */
948     {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */
949     {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */
950     {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */
951     {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */
952     {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */
953     {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */
954     {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */
955     {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */
956     {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */
957     {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */
958 };
959 
960 /** HUF_selectDecoder() :
961  *  Tells which decoder is likely to decode faster,
962  *  based on a set of pre-computed metrics.
963  * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
964  *  Assumption : 0 < dstSize <= 128 KB */
HUF_selectDecoder(size_t dstSize,size_t cSrcSize)965 U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
966 {
967     assert(dstSize > 0);
968     assert(dstSize <= 128*1024);
969     /* decoder timing evaluation */
970     {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */
971         U32 const D256 = (U32)(dstSize >> 8);
972         U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
973         U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
974         DTime1 += DTime1 >> 3;  /* advantage to algorithm using less memory, to reduce cache eviction */
975         return DTime1 < DTime0;
976 }   }
977 
978 
979 typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
980 
HUF_decompress(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)981 size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
982 {
983     static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 };
984 
985     /* validation checks */
986     if (dstSize == 0) return ERROR(dstSize_tooSmall);
987     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
988     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
989     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
990 
991     {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
992         return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
993     }
994 }
995 
HUF_decompress4X_DCtx(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)996 size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
997 {
998     /* validation checks */
999     if (dstSize == 0) return ERROR(dstSize_tooSmall);
1000     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
1001     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
1002     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
1003 
1004     {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1005         return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
1006                         HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
1007     }
1008 }
1009 
HUF_decompress4X_hufOnly(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)1010 size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
1011 {
1012     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
1013     return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
1014                                          workSpace, sizeof(workSpace));
1015 }
1016 
1017 
HUF_decompress4X_hufOnly_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize)1018 size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,
1019                                      size_t dstSize, const void* cSrc,
1020                                      size_t cSrcSize, void* workSpace,
1021                                      size_t wkspSize)
1022 {
1023     /* validation checks */
1024     if (dstSize == 0) return ERROR(dstSize_tooSmall);
1025     if (cSrcSize == 0) return ERROR(corruption_detected);
1026 
1027     {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1028         return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize):
1029                         HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
1030     }
1031 }
1032 
HUF_decompress1X_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize)1033 size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
1034                                   const void* cSrc, size_t cSrcSize,
1035                                   void* workSpace, size_t wkspSize)
1036 {
1037     /* validation checks */
1038     if (dstSize == 0) return ERROR(dstSize_tooSmall);
1039     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
1040     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
1041     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
1042 
1043     {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1044         return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
1045                                 cSrcSize, workSpace, wkspSize):
1046                         HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
1047                                 cSrcSize, workSpace, wkspSize);
1048     }
1049 }
1050 
HUF_decompress1X_DCtx(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)1051 size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
1052                              const void* cSrc, size_t cSrcSize)
1053 {
1054     U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
1055     return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
1056                                       workSpace, sizeof(workSpace));
1057 }
1058 
1059 
HUF_decompress1X_usingDTable_bmi2(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable,int bmi2)1060 size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
1061 {
1062     DTableDesc const dtd = HUF_getDTableDesc(DTable);
1063     return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
1064                            HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
1065 }
1066 
HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize,int bmi2)1067 size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
1068 {
1069     const BYTE* ip = (const BYTE*) cSrc;
1070 
1071     size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize);
1072     if (HUF_isError(hSize)) return hSize;
1073     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1074     ip += hSize; cSrcSize -= hSize;
1075 
1076     return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
1077 }
1078 
HUF_decompress4X_usingDTable_bmi2(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable,int bmi2)1079 size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
1080 {
1081     DTableDesc const dtd = HUF_getDTableDesc(DTable);
1082     return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
1083                            HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
1084 }
1085 
HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workSpace,size_t wkspSize,int bmi2)1086 size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
1087 {
1088     /* validation checks */
1089     if (dstSize == 0) return ERROR(dstSize_tooSmall);
1090     if (cSrcSize == 0) return ERROR(corruption_detected);
1091 
1092     {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1093         return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
1094                         HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
1095     }
1096 }
1097