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