1 // SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
2 /*
3 * Huffman decoder, part of New Generation Entropy library
4 * Copyright (C) 2013-2016, Yann Collet.
5 *
6 * You can contact the author at :
7 * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
8 */
9
10 /* **************************************************************
11 * Compiler specifics
12 ****************************************************************/
13 #define FORCE_INLINE static __always_inline
14
15 /* **************************************************************
16 * Dependencies
17 ****************************************************************/
18 #include "bitstream.h" /* BIT_* */
19 #include "fse.h" /* header compression */
20 #include "huf.h"
21 #include <linux/compiler.h>
22 #include <linux/kernel.h>
23 #include <linux/string.h> /* memcpy, memset */
24
25 /* **************************************************************
26 * Error Management
27 ****************************************************************/
28 #define HUF_STATIC_ASSERT(c) \
29 { \
30 enum { HUF_static_assert = 1 / (int)(!!(c)) }; \
31 } /* use only *after* variable declarations */
32
33 /*-***************************/
34 /* generic DTableDesc */
35 /*-***************************/
36
37 typedef struct {
38 BYTE maxTableLog;
39 BYTE tableType;
40 BYTE tableLog;
41 BYTE reserved;
42 } DTableDesc;
43
HUF_getDTableDesc(const HUF_DTable * table)44 static DTableDesc HUF_getDTableDesc(const HUF_DTable *table)
45 {
46 DTableDesc dtd;
47 memcpy(&dtd, table, sizeof(dtd));
48 return dtd;
49 }
50
51 /*-***************************/
52 /* single-symbol decoding */
53 /*-***************************/
54
55 typedef struct {
56 BYTE byte;
57 BYTE nbBits;
58 } HUF_DEltX2; /* single-symbol decoding */
59
HUF_readDTableX2_wksp(HUF_DTable * DTable,const void * src,size_t srcSize,void * workspace,size_t workspaceSize)60 size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
61 {
62 U32 tableLog = 0;
63 U32 nbSymbols = 0;
64 size_t iSize;
65 void *const dtPtr = DTable + 1;
66 HUF_DEltX2 *const dt = (HUF_DEltX2 *)dtPtr;
67
68 U32 *rankVal;
69 BYTE *huffWeight;
70 size_t spaceUsed32 = 0;
71
72 rankVal = (U32 *)workspace + spaceUsed32;
73 spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;
74 huffWeight = (BYTE *)((U32 *)workspace + spaceUsed32);
75 spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
76
77 if ((spaceUsed32 << 2) > workspaceSize)
78 return ERROR(tableLog_tooLarge);
79 workspace = (U32 *)workspace + spaceUsed32;
80 workspaceSize -= (spaceUsed32 << 2);
81
82 HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
83 /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
84
85 iSize = HUF_readStats_wksp(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
86 if (HUF_isError(iSize))
87 return iSize;
88
89 /* Table header */
90 {
91 DTableDesc dtd = HUF_getDTableDesc(DTable);
92 if (tableLog > (U32)(dtd.maxTableLog + 1))
93 return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
94 dtd.tableType = 0;
95 dtd.tableLog = (BYTE)tableLog;
96 memcpy(DTable, &dtd, sizeof(dtd));
97 }
98
99 /* Calculate starting value for each rank */
100 {
101 U32 n, nextRankStart = 0;
102 for (n = 1; n < tableLog + 1; n++) {
103 U32 const curr = nextRankStart;
104 nextRankStart += (rankVal[n] << (n - 1));
105 rankVal[n] = curr;
106 }
107 }
108
109 /* fill DTable */
110 {
111 U32 n;
112 for (n = 0; n < nbSymbols; n++) {
113 U32 const w = huffWeight[n];
114 U32 const length = (1 << w) >> 1;
115 U32 u;
116 HUF_DEltX2 D;
117 D.byte = (BYTE)n;
118 D.nbBits = (BYTE)(tableLog + 1 - w);
119 for (u = rankVal[w]; u < rankVal[w] + length; u++)
120 dt[u] = D;
121 rankVal[w] += length;
122 }
123 }
124
125 return iSize;
126 }
127
HUF_decodeSymbolX2(BIT_DStream_t * Dstream,const HUF_DEltX2 * dt,const U32 dtLog)128 static BYTE HUF_decodeSymbolX2(BIT_DStream_t *Dstream, const HUF_DEltX2 *dt, const U32 dtLog)
129 {
130 size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
131 BYTE const c = dt[val].byte;
132 BIT_skipBits(Dstream, dt[val].nbBits);
133 return c;
134 }
135
136 #define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
137
138 #define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
139 if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
140 HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
141
142 #define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
143 if (ZSTD_64bits()) \
144 HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
145
HUF_decodeStreamX2(BYTE * p,BIT_DStream_t * const bitDPtr,BYTE * const pEnd,const HUF_DEltX2 * const dt,const U32 dtLog)146 FORCE_INLINE size_t HUF_decodeStreamX2(BYTE *p, BIT_DStream_t *const bitDPtr, BYTE *const pEnd, const HUF_DEltX2 *const dt, const U32 dtLog)
147 {
148 BYTE *const pStart = p;
149
150 /* up to 4 symbols at a time */
151 while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 4)) {
152 HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
153 HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
154 HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
155 HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
156 }
157
158 /* closer to the end */
159 while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
160 HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
161
162 /* no more data to retrieve from bitstream, hence no need to reload */
163 while (p < pEnd)
164 HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
165
166 return pEnd - pStart;
167 }
168
HUF_decompress1X2_usingDTable_internal(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)169 static size_t HUF_decompress1X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
170 {
171 BYTE *op = (BYTE *)dst;
172 BYTE *const oend = op + dstSize;
173 const void *dtPtr = DTable + 1;
174 const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
175 BIT_DStream_t bitD;
176 DTableDesc const dtd = HUF_getDTableDesc(DTable);
177 U32 const dtLog = dtd.tableLog;
178
179 {
180 size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
181 if (HUF_isError(errorCode))
182 return errorCode;
183 }
184
185 HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
186
187 /* check */
188 if (!BIT_endOfDStream(&bitD))
189 return ERROR(corruption_detected);
190
191 return dstSize;
192 }
193
HUF_decompress1X2_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)194 size_t HUF_decompress1X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
195 {
196 DTableDesc dtd = HUF_getDTableDesc(DTable);
197 if (dtd.tableType != 0)
198 return ERROR(GENERIC);
199 return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
200 }
201
HUF_decompress1X2_DCtx_wksp(HUF_DTable * DCtx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)202 size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
203 {
204 const BYTE *ip = (const BYTE *)cSrc;
205
206 size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
207 if (HUF_isError(hSize))
208 return hSize;
209 if (hSize >= cSrcSize)
210 return ERROR(srcSize_wrong);
211 ip += hSize;
212 cSrcSize -= hSize;
213
214 return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
215 }
216
HUF_decompress4X2_usingDTable_internal(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)217 static size_t HUF_decompress4X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
218 {
219 /* Check */
220 if (cSrcSize < 10)
221 return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
222
223 {
224 const BYTE *const istart = (const BYTE *)cSrc;
225 BYTE *const ostart = (BYTE *)dst;
226 BYTE *const oend = ostart + dstSize;
227 const void *const dtPtr = DTable + 1;
228 const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
229
230 /* Init */
231 BIT_DStream_t bitD1;
232 BIT_DStream_t bitD2;
233 BIT_DStream_t bitD3;
234 BIT_DStream_t bitD4;
235 size_t const length1 = ZSTD_readLE16(istart);
236 size_t const length2 = ZSTD_readLE16(istart + 2);
237 size_t const length3 = ZSTD_readLE16(istart + 4);
238 size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
239 const BYTE *const istart1 = istart + 6; /* jumpTable */
240 const BYTE *const istart2 = istart1 + length1;
241 const BYTE *const istart3 = istart2 + length2;
242 const BYTE *const istart4 = istart3 + length3;
243 const size_t segmentSize = (dstSize + 3) / 4;
244 BYTE *const opStart2 = ostart + segmentSize;
245 BYTE *const opStart3 = opStart2 + segmentSize;
246 BYTE *const opStart4 = opStart3 + segmentSize;
247 BYTE *op1 = ostart;
248 BYTE *op2 = opStart2;
249 BYTE *op3 = opStart3;
250 BYTE *op4 = opStart4;
251 U32 endSignal;
252 DTableDesc const dtd = HUF_getDTableDesc(DTable);
253 U32 const dtLog = dtd.tableLog;
254
255 if (length4 > cSrcSize)
256 return ERROR(corruption_detected); /* overflow */
257 {
258 size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
259 if (HUF_isError(errorCode))
260 return errorCode;
261 }
262 {
263 size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
264 if (HUF_isError(errorCode))
265 return errorCode;
266 }
267 {
268 size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
269 if (HUF_isError(errorCode))
270 return errorCode;
271 }
272 {
273 size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
274 if (HUF_isError(errorCode))
275 return errorCode;
276 }
277
278 /* 16-32 symbols per loop (4-8 symbols per stream) */
279 endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
280 for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) {
281 HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
282 HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
283 HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
284 HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
285 HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
286 HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
287 HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
288 HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
289 HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
290 HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
291 HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
292 HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
293 HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
294 HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
295 HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
296 HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
297 endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
298 }
299
300 /* check corruption */
301 if (op1 > opStart2)
302 return ERROR(corruption_detected);
303 if (op2 > opStart3)
304 return ERROR(corruption_detected);
305 if (op3 > opStart4)
306 return ERROR(corruption_detected);
307 /* note : op4 supposed already verified within main loop */
308
309 /* finish bitStreams one by one */
310 HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
311 HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
312 HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
313 HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
314
315 /* check */
316 endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
317 if (!endSignal)
318 return ERROR(corruption_detected);
319
320 /* decoded size */
321 return dstSize;
322 }
323 }
324
HUF_decompress4X2_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)325 size_t HUF_decompress4X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
326 {
327 DTableDesc dtd = HUF_getDTableDesc(DTable);
328 if (dtd.tableType != 0)
329 return ERROR(GENERIC);
330 return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
331 }
332
HUF_decompress4X2_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)333 size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
334 {
335 const BYTE *ip = (const BYTE *)cSrc;
336
337 size_t const hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
338 if (HUF_isError(hSize))
339 return hSize;
340 if (hSize >= cSrcSize)
341 return ERROR(srcSize_wrong);
342 ip += hSize;
343 cSrcSize -= hSize;
344
345 return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
346 }
347
348 /* *************************/
349 /* double-symbols decoding */
350 /* *************************/
351 typedef struct {
352 U16 sequence;
353 BYTE nbBits;
354 BYTE length;
355 } HUF_DEltX4; /* double-symbols decoding */
356
357 typedef struct {
358 BYTE symbol;
359 BYTE weight;
360 } sortedSymbol_t;
361
362 /* HUF_fillDTableX4Level2() :
363 * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
HUF_fillDTableX4Level2(HUF_DEltX4 * DTable,U32 sizeLog,const U32 consumed,const U32 * rankValOrigin,const int minWeight,const sortedSymbol_t * sortedSymbols,const U32 sortedListSize,U32 nbBitsBaseline,U16 baseSeq)364 static void HUF_fillDTableX4Level2(HUF_DEltX4 *DTable, U32 sizeLog, const U32 consumed, const U32 *rankValOrigin, const int minWeight,
365 const sortedSymbol_t *sortedSymbols, const U32 sortedListSize, U32 nbBitsBaseline, U16 baseSeq)
366 {
367 HUF_DEltX4 DElt;
368 U32 rankVal[HUF_TABLELOG_MAX + 1];
369
370 /* get pre-calculated rankVal */
371 memcpy(rankVal, rankValOrigin, sizeof(rankVal));
372
373 /* fill skipped values */
374 if (minWeight > 1) {
375 U32 i, skipSize = rankVal[minWeight];
376 ZSTD_writeLE16(&(DElt.sequence), baseSeq);
377 DElt.nbBits = (BYTE)(consumed);
378 DElt.length = 1;
379 for (i = 0; i < skipSize; i++)
380 DTable[i] = DElt;
381 }
382
383 /* fill DTable */
384 {
385 U32 s;
386 for (s = 0; s < sortedListSize; s++) { /* note : sortedSymbols already skipped */
387 const U32 symbol = sortedSymbols[s].symbol;
388 const U32 weight = sortedSymbols[s].weight;
389 const U32 nbBits = nbBitsBaseline - weight;
390 const U32 length = 1 << (sizeLog - nbBits);
391 const U32 start = rankVal[weight];
392 U32 i = start;
393 const U32 end = start + length;
394
395 ZSTD_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
396 DElt.nbBits = (BYTE)(nbBits + consumed);
397 DElt.length = 2;
398 do {
399 DTable[i++] = DElt;
400 } while (i < end); /* since length >= 1 */
401
402 rankVal[weight] += length;
403 }
404 }
405 }
406
407 typedef U32 rankVal_t[HUF_TABLELOG_MAX][HUF_TABLELOG_MAX + 1];
408 typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
409
HUF_fillDTableX4(HUF_DEltX4 * DTable,const U32 targetLog,const sortedSymbol_t * sortedList,const U32 sortedListSize,const U32 * rankStart,rankVal_t rankValOrigin,const U32 maxWeight,const U32 nbBitsBaseline)410 static void HUF_fillDTableX4(HUF_DEltX4 *DTable, const U32 targetLog, const sortedSymbol_t *sortedList, const U32 sortedListSize, const U32 *rankStart,
411 rankVal_t rankValOrigin, const U32 maxWeight, const U32 nbBitsBaseline)
412 {
413 U32 rankVal[HUF_TABLELOG_MAX + 1];
414 const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
415 const U32 minBits = nbBitsBaseline - maxWeight;
416 U32 s;
417
418 memcpy(rankVal, rankValOrigin, sizeof(rankVal));
419
420 /* fill DTable */
421 for (s = 0; s < sortedListSize; s++) {
422 const U16 symbol = sortedList[s].symbol;
423 const U32 weight = sortedList[s].weight;
424 const U32 nbBits = nbBitsBaseline - weight;
425 const U32 start = rankVal[weight];
426 const U32 length = 1 << (targetLog - nbBits);
427
428 if (targetLog - nbBits >= minBits) { /* enough room for a second symbol */
429 U32 sortedRank;
430 int minWeight = nbBits + scaleLog;
431 if (minWeight < 1)
432 minWeight = 1;
433 sortedRank = rankStart[minWeight];
434 HUF_fillDTableX4Level2(DTable + start, targetLog - nbBits, nbBits, rankValOrigin[nbBits], minWeight, sortedList + sortedRank,
435 sortedListSize - sortedRank, nbBitsBaseline, symbol);
436 } else {
437 HUF_DEltX4 DElt;
438 ZSTD_writeLE16(&(DElt.sequence), symbol);
439 DElt.nbBits = (BYTE)(nbBits);
440 DElt.length = 1;
441 {
442 U32 const end = start + length;
443 U32 u;
444 for (u = start; u < end; u++)
445 DTable[u] = DElt;
446 }
447 }
448 rankVal[weight] += length;
449 }
450 }
451
HUF_readDTableX4_wksp(HUF_DTable * DTable,const void * src,size_t srcSize,void * workspace,size_t workspaceSize)452 size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
453 {
454 U32 tableLog, maxW, sizeOfSort, nbSymbols;
455 DTableDesc dtd = HUF_getDTableDesc(DTable);
456 U32 const maxTableLog = dtd.maxTableLog;
457 size_t iSize;
458 void *dtPtr = DTable + 1; /* force compiler to avoid strict-aliasing */
459 HUF_DEltX4 *const dt = (HUF_DEltX4 *)dtPtr;
460 U32 *rankStart;
461
462 rankValCol_t *rankVal;
463 U32 *rankStats;
464 U32 *rankStart0;
465 sortedSymbol_t *sortedSymbol;
466 BYTE *weightList;
467 size_t spaceUsed32 = 0;
468
469 HUF_STATIC_ASSERT((sizeof(rankValCol_t) & 3) == 0);
470
471 rankVal = (rankValCol_t *)((U32 *)workspace + spaceUsed32);
472 spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
473 rankStats = (U32 *)workspace + spaceUsed32;
474 spaceUsed32 += HUF_TABLELOG_MAX + 1;
475 rankStart0 = (U32 *)workspace + spaceUsed32;
476 spaceUsed32 += HUF_TABLELOG_MAX + 2;
477 sortedSymbol = (sortedSymbol_t *)((U32 *)workspace + spaceUsed32);
478 spaceUsed32 += ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
479 weightList = (BYTE *)((U32 *)workspace + spaceUsed32);
480 spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
481
482 if ((spaceUsed32 << 2) > workspaceSize)
483 return ERROR(tableLog_tooLarge);
484 workspace = (U32 *)workspace + spaceUsed32;
485 workspaceSize -= (spaceUsed32 << 2);
486
487 rankStart = rankStart0 + 1;
488 memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
489
490 HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
491 if (maxTableLog > HUF_TABLELOG_MAX)
492 return ERROR(tableLog_tooLarge);
493 /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
494
495 iSize = HUF_readStats_wksp(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
496 if (HUF_isError(iSize))
497 return iSize;
498
499 /* check result */
500 if (tableLog > maxTableLog)
501 return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
502
503 /* find maxWeight */
504 for (maxW = tableLog; rankStats[maxW] == 0; maxW--) {
505 } /* necessarily finds a solution before 0 */
506
507 /* Get start index of each weight */
508 {
509 U32 w, nextRankStart = 0;
510 for (w = 1; w < maxW + 1; w++) {
511 U32 curr = nextRankStart;
512 nextRankStart += rankStats[w];
513 rankStart[w] = curr;
514 }
515 rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
516 sizeOfSort = nextRankStart;
517 }
518
519 /* sort symbols by weight */
520 {
521 U32 s;
522 for (s = 0; s < nbSymbols; s++) {
523 U32 const w = weightList[s];
524 U32 const r = rankStart[w]++;
525 sortedSymbol[r].symbol = (BYTE)s;
526 sortedSymbol[r].weight = (BYTE)w;
527 }
528 rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
529 }
530
531 /* Build rankVal */
532 {
533 U32 *const rankVal0 = rankVal[0];
534 {
535 int const rescale = (maxTableLog - tableLog) - 1; /* tableLog <= maxTableLog */
536 U32 nextRankVal = 0;
537 U32 w;
538 for (w = 1; w < maxW + 1; w++) {
539 U32 curr = nextRankVal;
540 nextRankVal += rankStats[w] << (w + rescale);
541 rankVal0[w] = curr;
542 }
543 }
544 {
545 U32 const minBits = tableLog + 1 - maxW;
546 U32 consumed;
547 for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
548 U32 *const rankValPtr = rankVal[consumed];
549 U32 w;
550 for (w = 1; w < maxW + 1; w++) {
551 rankValPtr[w] = rankVal0[w] >> consumed;
552 }
553 }
554 }
555 }
556
557 HUF_fillDTableX4(dt, maxTableLog, sortedSymbol, sizeOfSort, rankStart0, rankVal, maxW, tableLog + 1);
558
559 dtd.tableLog = (BYTE)maxTableLog;
560 dtd.tableType = 1;
561 memcpy(DTable, &dtd, sizeof(dtd));
562 return iSize;
563 }
564
HUF_decodeSymbolX4(void * op,BIT_DStream_t * DStream,const HUF_DEltX4 * dt,const U32 dtLog)565 static U32 HUF_decodeSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
566 {
567 size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
568 memcpy(op, dt + val, 2);
569 BIT_skipBits(DStream, dt[val].nbBits);
570 return dt[val].length;
571 }
572
HUF_decodeLastSymbolX4(void * op,BIT_DStream_t * DStream,const HUF_DEltX4 * dt,const U32 dtLog)573 static U32 HUF_decodeLastSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
574 {
575 size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
576 memcpy(op, dt + val, 1);
577 if (dt[val].length == 1)
578 BIT_skipBits(DStream, dt[val].nbBits);
579 else {
580 if (DStream->bitsConsumed < (sizeof(DStream->bitContainer) * 8)) {
581 BIT_skipBits(DStream, dt[val].nbBits);
582 if (DStream->bitsConsumed > (sizeof(DStream->bitContainer) * 8))
583 /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
584 DStream->bitsConsumed = (sizeof(DStream->bitContainer) * 8);
585 }
586 }
587 return 1;
588 }
589
590 #define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
591
592 #define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
593 if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
594 ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
595
596 #define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
597 if (ZSTD_64bits()) \
598 ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
599
HUF_decodeStreamX4(BYTE * p,BIT_DStream_t * bitDPtr,BYTE * const pEnd,const HUF_DEltX4 * const dt,const U32 dtLog)600 FORCE_INLINE size_t HUF_decodeStreamX4(BYTE *p, BIT_DStream_t *bitDPtr, BYTE *const pEnd, const HUF_DEltX4 *const dt, const U32 dtLog)
601 {
602 BYTE *const pStart = p;
603
604 /* up to 8 symbols at a time */
605 while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd - (sizeof(bitDPtr->bitContainer) - 1))) {
606 HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
607 HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
608 HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
609 HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
610 }
611
612 /* closer to end : up to 2 symbols at a time */
613 while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd - 2))
614 HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
615
616 while (p <= pEnd - 2)
617 HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
618
619 if (p < pEnd)
620 p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
621
622 return p - pStart;
623 }
624
HUF_decompress1X4_usingDTable_internal(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)625 static size_t HUF_decompress1X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
626 {
627 BIT_DStream_t bitD;
628
629 /* Init */
630 {
631 size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
632 if (HUF_isError(errorCode))
633 return errorCode;
634 }
635
636 /* decode */
637 {
638 BYTE *const ostart = (BYTE *)dst;
639 BYTE *const oend = ostart + dstSize;
640 const void *const dtPtr = DTable + 1; /* force compiler to not use strict-aliasing */
641 const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
642 DTableDesc const dtd = HUF_getDTableDesc(DTable);
643 HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
644 }
645
646 /* check */
647 if (!BIT_endOfDStream(&bitD))
648 return ERROR(corruption_detected);
649
650 /* decoded size */
651 return dstSize;
652 }
653
HUF_decompress1X4_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)654 size_t HUF_decompress1X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
655 {
656 DTableDesc dtd = HUF_getDTableDesc(DTable);
657 if (dtd.tableType != 1)
658 return ERROR(GENERIC);
659 return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
660 }
661
HUF_decompress1X4_DCtx_wksp(HUF_DTable * DCtx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)662 size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
663 {
664 const BYTE *ip = (const BYTE *)cSrc;
665
666 size_t const hSize = HUF_readDTableX4_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
667 if (HUF_isError(hSize))
668 return hSize;
669 if (hSize >= cSrcSize)
670 return ERROR(srcSize_wrong);
671 ip += hSize;
672 cSrcSize -= hSize;
673
674 return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
675 }
676
HUF_decompress4X4_usingDTable_internal(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)677 static size_t HUF_decompress4X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
678 {
679 if (cSrcSize < 10)
680 return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
681
682 {
683 const BYTE *const istart = (const BYTE *)cSrc;
684 BYTE *const ostart = (BYTE *)dst;
685 BYTE *const oend = ostart + dstSize;
686 const void *const dtPtr = DTable + 1;
687 const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
688
689 /* Init */
690 BIT_DStream_t bitD1;
691 BIT_DStream_t bitD2;
692 BIT_DStream_t bitD3;
693 BIT_DStream_t bitD4;
694 size_t const length1 = ZSTD_readLE16(istart);
695 size_t const length2 = ZSTD_readLE16(istart + 2);
696 size_t const length3 = ZSTD_readLE16(istart + 4);
697 size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
698 const BYTE *const istart1 = istart + 6; /* jumpTable */
699 const BYTE *const istart2 = istart1 + length1;
700 const BYTE *const istart3 = istart2 + length2;
701 const BYTE *const istart4 = istart3 + length3;
702 size_t const segmentSize = (dstSize + 3) / 4;
703 BYTE *const opStart2 = ostart + segmentSize;
704 BYTE *const opStart3 = opStart2 + segmentSize;
705 BYTE *const opStart4 = opStart3 + segmentSize;
706 BYTE *op1 = ostart;
707 BYTE *op2 = opStart2;
708 BYTE *op3 = opStart3;
709 BYTE *op4 = opStart4;
710 U32 endSignal;
711 DTableDesc const dtd = HUF_getDTableDesc(DTable);
712 U32 const dtLog = dtd.tableLog;
713
714 if (length4 > cSrcSize)
715 return ERROR(corruption_detected); /* overflow */
716 {
717 size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
718 if (HUF_isError(errorCode))
719 return errorCode;
720 }
721 {
722 size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
723 if (HUF_isError(errorCode))
724 return errorCode;
725 }
726 {
727 size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
728 if (HUF_isError(errorCode))
729 return errorCode;
730 }
731 {
732 size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
733 if (HUF_isError(errorCode))
734 return errorCode;
735 }
736
737 /* 16-32 symbols per loop (4-8 symbols per stream) */
738 endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
739 for (; (endSignal == BIT_DStream_unfinished) & (op4 < (oend - (sizeof(bitD4.bitContainer) - 1)));) {
740 HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
741 HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
742 HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
743 HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
744 HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
745 HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
746 HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
747 HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
748 HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
749 HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
750 HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
751 HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
752 HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
753 HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
754 HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
755 HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
756
757 endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
758 }
759
760 /* check corruption */
761 if (op1 > opStart2)
762 return ERROR(corruption_detected);
763 if (op2 > opStart3)
764 return ERROR(corruption_detected);
765 if (op3 > opStart4)
766 return ERROR(corruption_detected);
767 /* note : op4 already verified within main loop */
768
769 /* finish bitStreams one by one */
770 HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
771 HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
772 HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
773 HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
774
775 /* check */
776 {
777 U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
778 if (!endCheck)
779 return ERROR(corruption_detected);
780 }
781
782 /* decoded size */
783 return dstSize;
784 }
785 }
786
HUF_decompress4X4_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)787 size_t HUF_decompress4X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
788 {
789 DTableDesc dtd = HUF_getDTableDesc(DTable);
790 if (dtd.tableType != 1)
791 return ERROR(GENERIC);
792 return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
793 }
794
HUF_decompress4X4_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)795 size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
796 {
797 const BYTE *ip = (const BYTE *)cSrc;
798
799 size_t hSize = HUF_readDTableX4_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
800 if (HUF_isError(hSize))
801 return hSize;
802 if (hSize >= cSrcSize)
803 return ERROR(srcSize_wrong);
804 ip += hSize;
805 cSrcSize -= hSize;
806
807 return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
808 }
809
810 /* ********************************/
811 /* Generic decompression selector */
812 /* ********************************/
813
HUF_decompress1X_usingDTable(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)814 size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
815 {
816 DTableDesc const dtd = HUF_getDTableDesc(DTable);
817 return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
818 : HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
819 }
820
HUF_decompress4X_usingDTable(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const HUF_DTable * DTable)821 size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
822 {
823 DTableDesc const dtd = HUF_getDTableDesc(DTable);
824 return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
825 : HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
826 }
827
828 typedef struct {
829 U32 tableTime;
830 U32 decode256Time;
831 } algo_time_t;
832 static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = {
833 /* single, double, quad */
834 {{0, 0}, {1, 1}, {2, 2}}, /* Q==0 : impossible */
835 {{0, 0}, {1, 1}, {2, 2}}, /* Q==1 : impossible */
836 {{38, 130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
837 {{448, 128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
838 {{556, 128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
839 {{714, 128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
840 {{883, 128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
841 {{897, 128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
842 {{926, 128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
843 {{947, 128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
844 {{1107, 128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
845 {{1177, 128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
846 {{1242, 128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
847 {{1349, 128}, {2644, 106}, {5260, 106}}, /* Q ==13 : 81-87% */
848 {{1455, 128}, {2422, 124}, {4174, 124}}, /* Q ==14 : 87-93% */
849 {{722, 128}, {1891, 145}, {1936, 146}}, /* Q ==15 : 93-99% */
850 };
851
852 /** HUF_selectDecoder() :
853 * Tells which decoder is likely to decode faster,
854 * based on a set of pre-determined metrics.
855 * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
856 * Assumption : 0 < cSrcSize < dstSize <= 128 KB */
HUF_selectDecoder(size_t dstSize,size_t cSrcSize)857 U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize)
858 {
859 /* decoder timing evaluation */
860 U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
861 U32 const D256 = (U32)(dstSize >> 8);
862 U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
863 U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
864 DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
865
866 return DTime1 < DTime0;
867 }
868
869 typedef size_t (*decompressionAlgo)(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize);
870
HUF_decompress4X_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)871 size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
872 {
873 /* validation checks */
874 if (dstSize == 0)
875 return ERROR(dstSize_tooSmall);
876 if (cSrcSize > dstSize)
877 return ERROR(corruption_detected); /* invalid */
878 if (cSrcSize == dstSize) {
879 memcpy(dst, cSrc, dstSize);
880 return dstSize;
881 } /* not compressed */
882 if (cSrcSize == 1) {
883 memset(dst, *(const BYTE *)cSrc, dstSize);
884 return dstSize;
885 } /* RLE */
886
887 {
888 U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
889 return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
890 : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
891 }
892 }
893
HUF_decompress4X_hufOnly_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)894 size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
895 {
896 /* validation checks */
897 if (dstSize == 0)
898 return ERROR(dstSize_tooSmall);
899 if ((cSrcSize >= dstSize) || (cSrcSize <= 1))
900 return ERROR(corruption_detected); /* invalid */
901
902 {
903 U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
904 return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
905 : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
906 }
907 }
908
HUF_decompress1X_DCtx_wksp(HUF_DTable * dctx,void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,void * workspace,size_t workspaceSize)909 size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
910 {
911 /* validation checks */
912 if (dstSize == 0)
913 return ERROR(dstSize_tooSmall);
914 if (cSrcSize > dstSize)
915 return ERROR(corruption_detected); /* invalid */
916 if (cSrcSize == dstSize) {
917 memcpy(dst, cSrc, dstSize);
918 return dstSize;
919 } /* not compressed */
920 if (cSrcSize == 1) {
921 memset(dst, *(const BYTE *)cSrc, dstSize);
922 return dstSize;
923 } /* RLE */
924
925 {
926 U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
927 return algoNb ? HUF_decompress1X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
928 : HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
929 }
930 }
931