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