Coverage Report

Created: 2026-01-10 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zstd/lib/decompress/huf_decompress.c
Line
Count
Source
1
/* ******************************************************************
2
 * huff0 huffman decoder,
3
 * part of Finite State Entropy library
4
 * Copyright (c) Meta Platforms, Inc. and affiliates.
5
 *
6
 *  You can contact the author at :
7
 *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
8
 *
9
 * This source code is licensed under both the BSD-style license (found in the
10
 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11
 * in the COPYING file in the root directory of this source tree).
12
 * You may select, at your option, one of the above-listed licenses.
13
****************************************************************** */
14
15
/* **************************************************************
16
*  Dependencies
17
****************************************************************/
18
#include <stddef.h>               /* size_t */
19
#include "../common/zstd_deps.h"  /* ZSTD_memcpy, ZSTD_memset */
20
#include "../common/compiler.h"
21
#include "../common/bitstream.h"  /* BIT_* */
22
#include "../common/fse.h"        /* to compress headers */
23
#include "../common/huf.h"
24
#include "../common/error_private.h"
25
#include "../common/zstd_internal.h"
26
#include "../common/bits.h"       /* ZSTD_highbit32, ZSTD_countTrailingZeros64 */
27
28
/* **************************************************************
29
*  Constants
30
****************************************************************/
31
32
64.1k
#define HUF_DECODER_FAST_TABLELOG 11
33
34
/* **************************************************************
35
*  Macros
36
****************************************************************/
37
38
#ifdef HUF_DISABLE_FAST_DECODE
39
# define HUF_ENABLE_FAST_DECODE 0
40
#else
41
5.91k
# define HUF_ENABLE_FAST_DECODE 1
42
#endif
43
44
/* These two optional macros force the use one way or another of the two
45
 * Huffman decompression implementations. You can't force in both directions
46
 * at the same time.
47
 */
48
#if defined(HUF_FORCE_DECOMPRESS_X1) && \
49
    defined(HUF_FORCE_DECOMPRESS_X2)
50
#error "Cannot force the use of the X1 and X2 decoders at the same time!"
51
#endif
52
53
/* When DYNAMIC_BMI2 is enabled, fast decoders are only called when bmi2 is
54
 * supported at runtime, so we can add the BMI2 target attribute.
55
 * When it is disabled, we will still get BMI2 if it is enabled statically.
56
 */
57
#if DYNAMIC_BMI2
58
# define HUF_FAST_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE
59
#else
60
# define HUF_FAST_BMI2_ATTRS
61
#endif
62
63
#ifdef __cplusplus
64
# define HUF_EXTERN_C extern "C"
65
#else
66
# define HUF_EXTERN_C
67
#endif
68
#define HUF_ASM_DECL HUF_EXTERN_C
69
70
#if DYNAMIC_BMI2
71
# define HUF_NEED_BMI2_FUNCTION 1
72
#else
73
# define HUF_NEED_BMI2_FUNCTION 0
74
#endif
75
76
/* **************************************************************
77
*  Error Management
78
****************************************************************/
79
25.1k
#define HUF_isError ERR_isError
80
81
82
/* **************************************************************
83
*  Byte alignment for workSpace management
84
****************************************************************/
85
#define HUF_ALIGN(x, a)         HUF_ALIGN_MASK((x), (a) - 1)
86
#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
87
88
89
/* **************************************************************
90
*  BMI2 Variant Wrappers
91
****************************************************************/
92
typedef size_t (*HUF_DecompressUsingDTableFn)(void *dst, size_t dstSize,
93
                                              const void *cSrc,
94
                                              size_t cSrcSize,
95
                                              const HUF_DTable *DTable);
96
97
#if DYNAMIC_BMI2
98
99
#define HUF_DGEN(fn)                                                        \
100
                                                                            \
101
    static size_t fn##_default(                                             \
102
                  void* dst,  size_t dstSize,                               \
103
            const void* cSrc, size_t cSrcSize,                              \
104
            const HUF_DTable* DTable)                                       \
105
0
    {                                                                       \
106
0
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
107
0
    }                                                                       \
Unexecuted instantiation: huf_decompress.c:HUF_decompress1X2_usingDTable_internal_default
Unexecuted instantiation: huf_decompress.c:HUF_decompress1X1_usingDTable_internal_default
108
                                                                            \
109
    static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2(                          \
110
                  void* dst,  size_t dstSize,                               \
111
            const void* cSrc, size_t cSrcSize,                              \
112
            const HUF_DTable* DTable)                                       \
113
5.99k
    {                                                                       \
114
5.99k
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
115
5.99k
    }                                                                       \
huf_decompress.c:HUF_decompress1X2_usingDTable_internal_bmi2
Line
Count
Source
113
1.67k
    {                                                                       \
114
1.67k
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
115
1.67k
    }                                                                       \
huf_decompress.c:HUF_decompress1X1_usingDTable_internal_bmi2
Line
Count
Source
113
4.31k
    {                                                                       \
114
4.31k
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
115
4.31k
    }                                                                       \
116
                                                                            \
117
    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \
118
                     size_t cSrcSize, HUF_DTable const* DTable, int flags)  \
119
5.99k
    {                                                                       \
120
5.99k
        if (flags & HUF_flags_bmi2) {                                       \
121
5.99k
            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
122
5.99k
        }                                                                   \
123
5.99k
        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
124
5.99k
    }
huf_decompress.c:HUF_decompress1X2_usingDTable_internal
Line
Count
Source
119
1.67k
    {                                                                       \
120
1.67k
        if (flags & HUF_flags_bmi2) {                                       \
121
1.67k
            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
122
1.67k
        }                                                                   \
123
1.67k
        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
124
1.67k
    }
huf_decompress.c:HUF_decompress1X1_usingDTable_internal
Line
Count
Source
119
4.31k
    {                                                                       \
120
4.31k
        if (flags & HUF_flags_bmi2) {                                       \
121
4.31k
            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
122
4.31k
        }                                                                   \
123
4.31k
        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
124
4.31k
    }
125
126
#else
127
128
#define HUF_DGEN(fn)                                                        \
129
    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \
130
                     size_t cSrcSize, HUF_DTable const* DTable, int flags)  \
131
    {                                                                       \
132
        (void)flags;                                                        \
133
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
134
    }
135
136
#endif
137
138
139
/*-***************************/
140
/*  generic DTableDesc       */
141
/*-***************************/
142
typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
143
144
static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
145
30.9k
{
146
30.9k
    DTableDesc dtd;
147
30.9k
    ZSTD_memcpy(&dtd, table, sizeof(dtd));
148
30.9k
    return dtd;
149
30.9k
}
150
151
9.16k
static size_t HUF_initFastDStream(BYTE const* ip) {
152
9.16k
    BYTE const lastByte = ip[7];
153
9.16k
    size_t const bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;
154
9.16k
    size_t const value = MEM_readLEST(ip) | 1;
155
9.16k
    assert(bitsConsumed <= 8);
156
9.16k
    assert(sizeof(size_t) == 8);
157
9.16k
    return value << bitsConsumed;
158
9.16k
}
159
160
161
/**
162
 * The input/output arguments to the Huffman fast decoding loop:
163
 *
164
 * ip [in/out] - The input pointers, must be updated to reflect what is consumed.
165
 * op [in/out] - The output pointers, must be updated to reflect what is written.
166
 * bits [in/out] - The bitstream containers, must be updated to reflect the current state.
167
 * dt [in] - The decoding table.
168
 * ilowest [in] - The beginning of the valid range of the input. Decoders may read
169
 *                down to this pointer. It may be below iend[0].
170
 * oend [in] - The end of the output stream. op[3] must not cross oend.
171
 * iend [in] - The end of each input stream. ip[i] may cross iend[i],
172
 *             as long as it is above ilowest, but that indicates corruption.
173
 */
174
typedef struct {
175
    BYTE const* ip[4];
176
    BYTE* op[4];
177
    U64 bits[4];
178
    void const* dt;
179
    BYTE const* ilowest;
180
    BYTE* oend;
181
    BYTE const* iend[4];
182
} HUF_DecompressFastArgs;
183
184
typedef void (*HUF_DecompressFastLoopFn)(HUF_DecompressFastArgs*);
185
186
/**
187
 * Initializes args for the fast decoding loop.
188
 * @returns 1 on success
189
 *          0 if the fallback implementation should be used.
190
 *          Or an error code on failure.
191
 */
192
static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)
193
2.95k
{
194
2.95k
    void const* dt = DTable + 1;
195
2.95k
    U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;
196
197
2.95k
    const BYTE* const istart = (const BYTE*)src;
198
199
2.95k
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
200
201
    /* The fast decoding loop assumes 64-bit little-endian.
202
     * This condition is false on x32.
203
     */
204
2.95k
    if (!MEM_isLittleEndian() || MEM_32bits())
205
0
        return 0;
206
207
    /* Avoid nullptr addition */
208
2.95k
    if (dstSize == 0)
209
0
        return 0;
210
2.95k
    assert(dst != NULL);
211
212
    /* strict minimum : jump table + 1 byte per stream */
213
2.95k
    if (srcSize < 10)
214
1
        return ERROR(corruption_detected);
215
216
    /* Must have at least 8 bytes per stream because we don't handle initializing smaller bit containers.
217
     * If table log is not correct at this point, fallback to the old decoder.
218
     * On small inputs we don't have enough data to trigger the fast loop, so use the old decoder.
219
     */
220
2.95k
    if (dtLog != HUF_DECODER_FAST_TABLELOG)
221
367
        return 0;
222
223
    /* Read the jump table. */
224
2.58k
    {
225
2.58k
        size_t const length1 = MEM_readLE16(istart);
226
2.58k
        size_t const length2 = MEM_readLE16(istart+2);
227
2.58k
        size_t const length3 = MEM_readLE16(istart+4);
228
2.58k
        size_t const length4 = srcSize - (length1 + length2 + length3 + 6);
229
2.58k
        args->iend[0] = istart + 6;  /* jumpTable */
230
2.58k
        args->iend[1] = args->iend[0] + length1;
231
2.58k
        args->iend[2] = args->iend[1] + length2;
232
2.58k
        args->iend[3] = args->iend[2] + length3;
233
234
        /* HUF_initFastDStream() requires this, and this small of an input
235
         * won't benefit from the ASM loop anyways.
236
         */
237
2.58k
        if (length1 < 8 || length2 < 8 || length3 < 8 || length4 < 8)
238
282
            return 0;
239
2.30k
        if (length4 > srcSize) return ERROR(corruption_detected);   /* overflow */
240
2.30k
    }
241
    /* ip[] contains the position that is currently loaded into bits[]. */
242
2.29k
    args->ip[0] = args->iend[1] - sizeof(U64);
243
2.29k
    args->ip[1] = args->iend[2] - sizeof(U64);
244
2.29k
    args->ip[2] = args->iend[3] - sizeof(U64);
245
2.29k
    args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64);
246
247
    /* op[] contains the output pointers. */
248
2.29k
    args->op[0] = (BYTE*)dst;
249
2.29k
    args->op[1] = args->op[0] + (dstSize+3)/4;
250
2.29k
    args->op[2] = args->op[1] + (dstSize+3)/4;
251
2.29k
    args->op[3] = args->op[2] + (dstSize+3)/4;
252
253
    /* No point to call the ASM loop for tiny outputs. */
254
2.29k
    if (args->op[3] >= oend)
255
1
        return 0;
256
257
    /* bits[] is the bit container.
258
        * It is read from the MSB down to the LSB.
259
        * It is shifted left as it is read, and zeros are
260
        * shifted in. After the lowest valid bit a 1 is
261
        * set, so that CountTrailingZeros(bits[]) can be used
262
        * to count how many bits we've consumed.
263
        */
264
2.29k
    args->bits[0] = HUF_initFastDStream(args->ip[0]);
265
2.29k
    args->bits[1] = HUF_initFastDStream(args->ip[1]);
266
2.29k
    args->bits[2] = HUF_initFastDStream(args->ip[2]);
267
2.29k
    args->bits[3] = HUF_initFastDStream(args->ip[3]);
268
269
    /* The decoders must be sure to never read beyond ilowest.
270
     * This is lower than iend[0], but allowing decoders to read
271
     * down to ilowest can allow an extra iteration or two in the
272
     * fast loop.
273
     */
274
2.29k
    args->ilowest = istart;
275
276
2.29k
    args->oend = oend;
277
2.29k
    args->dt = dt;
278
279
2.29k
    return 1;
280
2.29k
}
281
282
static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArgs const* args, int stream, BYTE* segmentEnd)
283
9.14k
{
284
    /* Validate that we haven't overwritten. */
285
9.14k
    if (args->op[stream] > segmentEnd)
286
0
        return ERROR(corruption_detected);
287
    /* Validate that we haven't read beyond iend[].
288
        * Note that ip[] may be < iend[] because the MSB is
289
        * the next bit to read, and we may have consumed 100%
290
        * of the stream, so down to iend[i] - 8 is valid.
291
        */
292
9.14k
    if (args->ip[stream] < args->iend[stream] - 8)
293
14
        return ERROR(corruption_detected);
294
295
    /* Construct the BIT_DStream_t. */
296
9.14k
    assert(sizeof(size_t) == 8);
297
9.12k
    bit->bitContainer = MEM_readLEST(args->ip[stream]);
298
9.12k
    bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]);
299
9.12k
    bit->start = (const char*)args->ilowest;
300
9.12k
    bit->limitPtr = bit->start + sizeof(size_t);
301
9.12k
    bit->ptr = (const char*)args->ip[stream];
302
303
9.12k
    return 0;
304
9.12k
}
305
306
/* Calls X(N) for each stream 0, 1, 2, 3. */
307
#define HUF_4X_FOR_EACH_STREAM(X) \
308
0
    do {                          \
309
0
        X(0);                     \
310
0
        X(1);                     \
311
0
        X(2);                     \
312
0
        X(3);                     \
313
0
    } while (0)
314
315
/* Calls X(N, var) for each stream 0, 1, 2, 3. */
316
#define HUF_4X_FOR_EACH_STREAM_WITH_VAR(X, var) \
317
0
    do {                                        \
318
0
        X(0, (var));                            \
319
0
        X(1, (var));                            \
320
0
        X(2, (var));                            \
321
0
        X(3, (var));                            \
322
0
    } while (0)
323
324
325
#ifndef HUF_FORCE_DECOMPRESS_X2
326
327
/*-***************************/
328
/*  single-symbol decoding   */
329
/*-***************************/
330
typedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1;   /* single-symbol decoding */
331
332
/**
333
 * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at
334
 * a time.
335
 */
336
76.8k
static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
337
76.8k
    U64 D4;
338
76.8k
    if (MEM_isLittleEndian()) {
339
76.8k
        D4 = (U64)((symbol << 8) + nbBits);
340
76.8k
    } else {
341
0
        D4 = (U64)(symbol + (nbBits << 8));
342
0
    }
343
76.8k
    assert(D4 < (1U << 16));
344
76.8k
    D4 *= 0x0001000100010001ULL;
345
76.8k
    return D4;
346
76.8k
}
347
348
/**
349
 * Increase the tableLog to targetTableLog and rescales the stats.
350
 * If tableLog > targetTableLog this is a no-op.
351
 * @returns New tableLog
352
 */
353
static U32 HUF_rescaleStats(BYTE* huffWeight, U32* rankVal, U32 nbSymbols, U32 tableLog, U32 targetTableLog)
354
5.57k
{
355
5.57k
    if (tableLog > targetTableLog)
356
441
        return tableLog;
357
5.13k
    if (tableLog < targetTableLog) {
358
4.74k
        U32 const scale = targetTableLog - tableLog;
359
4.74k
        U32 s;
360
        /* Increase the weight for all non-zero probability symbols by scale. */
361
191k
        for (s = 0; s < nbSymbols; ++s) {
362
186k
            huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale);
363
186k
        }
364
        /* Update rankVal to reflect the new weights.
365
         * All weights except 0 get moved to weight + scale.
366
         * Weights [1, scale] are empty.
367
         */
368
26.7k
        for (s = targetTableLog; s > scale; --s) {
369
21.9k
            rankVal[s] = rankVal[s - scale];
370
21.9k
        }
371
34.9k
        for (s = scale; s > 0; --s) {
372
30.2k
            rankVal[s] = 0;
373
30.2k
        }
374
4.74k
    }
375
5.13k
    return targetTableLog;
376
5.57k
}
377
378
typedef struct {
379
        U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];
380
        U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];
381
        U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
382
        BYTE symbols[HUF_SYMBOLVALUE_MAX + 1];
383
        BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
384
} HUF_ReadDTableX1_Workspace;
385
386
size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags)
387
5.71k
{
388
5.71k
    U32 tableLog = 0;
389
5.71k
    U32 nbSymbols = 0;
390
5.71k
    size_t iSize;
391
5.71k
    void* const dtPtr = DTable + 1;
392
5.71k
    HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
393
5.71k
    HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;
394
395
5.71k
    DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));
396
5.71k
    if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);
397
398
5.71k
    DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
399
    /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */
400
401
5.71k
    iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), flags);
402
5.71k
    if (HUF_isError(iSize)) return iSize;
403
404
405
    /* Table header */
406
5.57k
    {   DTableDesc dtd = HUF_getDTableDesc(DTable);
407
5.57k
        U32 const maxTableLog = dtd.maxTableLog + 1;
408
5.57k
        U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG);
409
5.57k
        tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog);
410
5.57k
        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */
411
5.57k
        dtd.tableType = 0;
412
5.57k
        dtd.tableLog = (BYTE)tableLog;
413
5.57k
        ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
414
5.57k
    }
415
416
    /* Compute symbols and rankStart given rankVal:
417
     *
418
     * rankVal already contains the number of values of each weight.
419
     *
420
     * symbols contains the symbols ordered by weight. First are the rankVal[0]
421
     * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on.
422
     * symbols[0] is filled (but unused) to avoid a branch.
423
     *
424
     * rankStart contains the offset where each rank belongs in the DTable.
425
     * rankStart[0] is not filled because there are no entries in the table for
426
     * weight 0.
427
     */
428
0
    {   int n;
429
5.57k
        U32 nextRankStart = 0;
430
5.57k
        int const unroll = 4;
431
5.57k
        int const nLimit = (int)nbSymbols - unroll + 1;
432
72.9k
        for (n=0; n<(int)tableLog+1; n++) {
433
67.3k
            U32 const curr = nextRankStart;
434
67.3k
            nextRankStart += wksp->rankVal[n];
435
67.3k
            wksp->rankStart[n] = curr;
436
67.3k
        }
437
67.8k
        for (n=0; n < nLimit; n += unroll) {
438
62.2k
            int u;
439
311k
            for (u=0; u < unroll; ++u) {
440
249k
                size_t const w = wksp->huffWeight[n+u];
441
249k
                wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);
442
249k
            }
443
62.2k
        }
444
14.5k
        for (; n < (int)nbSymbols; ++n) {
445
8.97k
            size_t const w = wksp->huffWeight[n];
446
8.97k
            wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;
447
8.97k
        }
448
5.57k
    }
449
450
    /* fill DTable
451
     * We fill all entries of each weight in order.
452
     * That way length is a constant for each iteration of the outer loop.
453
     * We can switch based on the length to a different inner loop which is
454
     * optimized for that particular case.
455
     */
456
5.57k
    {   U32 w;
457
5.57k
        int symbol = wksp->rankVal[0];
458
5.57k
        int rankStart = 0;
459
67.3k
        for (w=1; w<tableLog+1; ++w) {
460
61.7k
            int const symbolCount = wksp->rankVal[w];
461
61.7k
            int const length = (1 << w) >> 1;
462
61.7k
            int uStart = rankStart;
463
61.7k
            BYTE const nbBits = (BYTE)(tableLog + 1 - w);
464
61.7k
            int s;
465
61.7k
            int u;
466
61.7k
            switch (length) {
467
5.57k
            case 1:
468
30.6k
                for (s=0; s<symbolCount; ++s) {
469
25.0k
                    HUF_DEltX1 D;
470
25.0k
                    D.byte = wksp->symbols[symbol + s];
471
25.0k
                    D.nbBits = nbBits;
472
25.0k
                    dt[uStart] = D;
473
25.0k
                    uStart += 1;
474
25.0k
                }
475
5.57k
                break;
476
5.57k
            case 2:
477
11.6k
                for (s=0; s<symbolCount; ++s) {
478
6.03k
                    HUF_DEltX1 D;
479
6.03k
                    D.byte = wksp->symbols[symbol + s];
480
6.03k
                    D.nbBits = nbBits;
481
6.03k
                    dt[uStart+0] = D;
482
6.03k
                    dt[uStart+1] = D;
483
6.03k
                    uStart += 2;
484
6.03k
                }
485
5.57k
                break;
486
5.57k
            case 4:
487
13.5k
                for (s=0; s<symbolCount; ++s) {
488
7.98k
                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
489
7.98k
                    MEM_write64(dt + uStart, D4);
490
7.98k
                    uStart += 4;
491
7.98k
                }
492
5.57k
                break;
493
5.57k
            case 8:
494
12.3k
                for (s=0; s<symbolCount; ++s) {
495
6.79k
                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
496
6.79k
                    MEM_write64(dt + uStart, D4);
497
6.79k
                    MEM_write64(dt + uStart + 4, D4);
498
6.79k
                    uStart += 8;
499
6.79k
                }
500
5.57k
                break;
501
39.4k
            default:
502
101k
                for (s=0; s<symbolCount; ++s) {
503
62.0k
                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
504
824k
                    for (u=0; u < length; u += 16) {
505
762k
                        MEM_write64(dt + uStart + u + 0, D4);
506
762k
                        MEM_write64(dt + uStart + u + 4, D4);
507
762k
                        MEM_write64(dt + uStart + u + 8, D4);
508
762k
                        MEM_write64(dt + uStart + u + 12, D4);
509
762k
                    }
510
62.0k
                    assert(u == length);
511
62.0k
                    uStart += length;
512
62.0k
                }
513
39.4k
                break;
514
61.7k
            }
515
61.7k
            symbol += symbolCount;
516
61.7k
            rankStart += symbolCount * length;
517
61.7k
        }
518
5.57k
    }
519
5.57k
    return iSize;
520
5.57k
}
521
522
FORCE_INLINE_TEMPLATE BYTE
523
HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
524
335k
{
525
335k
    size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
526
335k
    BYTE const c = dt[val].byte;
527
335k
    BIT_skipBits(Dstream, dt[val].nbBits);
528
335k
    return c;
529
335k
}
530
531
#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
532
335k
    do { *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog); } while (0)
533
534
#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)      \
535
40.3k
    do {                                            \
536
40.3k
        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
537
40.3k
            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \
538
40.3k
    } while (0)
539
540
#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr)      \
541
80.7k
    do {                                            \
542
80.7k
        if (MEM_64bits())                           \
543
80.7k
            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \
544
80.7k
    } while (0)
545
546
HINT_INLINE size_t
547
HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)
548
11.9k
{
549
11.9k
    BYTE* const pStart = p;
550
551
    /* up to 4 symbols at a time */
552
11.9k
    if ((pEnd - p) > 3) {
553
44.7k
        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
554
38.1k
            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
555
38.1k
            HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
556
38.1k
            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
557
38.1k
            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
558
38.1k
        }
559
6.61k
    } else {
560
5.31k
        BIT_reloadDStream(bitDPtr);
561
5.31k
    }
562
563
    /* [0-3] symbols remaining */
564
11.9k
    if (MEM_32bits())
565
0
        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))
566
0
            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
567
568
    /* no more data to retrieve from bitstream, no need to reload */
569
185k
    while (p < pEnd)
570
173k
        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
571
572
11.9k
    return (size_t)(pEnd-pStart);
573
11.9k
}
574
575
FORCE_INLINE_TEMPLATE size_t
576
HUF_decompress1X1_usingDTable_internal_body(
577
          void* dst,  size_t dstSize,
578
    const void* cSrc, size_t cSrcSize,
579
    const HUF_DTable* DTable)
580
4.31k
{
581
4.31k
    BYTE* op = (BYTE*)dst;
582
4.31k
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(op, (ptrdiff_t)dstSize);
583
4.31k
    const void* dtPtr = DTable + 1;
584
4.31k
    const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
585
4.31k
    BIT_DStream_t bitD;
586
4.31k
    DTableDesc const dtd = HUF_getDTableDesc(DTable);
587
4.31k
    U32 const dtLog = dtd.tableLog;
588
589
4.31k
    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
590
591
4.30k
    HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);
592
593
4.30k
    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
594
595
4.24k
    return dstSize;
596
4.30k
}
597
598
/* HUF_decompress4X1_usingDTable_internal_body():
599
 * Conditions :
600
 * @dstSize >= 6
601
 */
602
FORCE_INLINE_TEMPLATE size_t
603
HUF_decompress4X1_usingDTable_internal_body(
604
          void* dst,  size_t dstSize,
605
    const void* cSrc, size_t cSrcSize,
606
    const HUF_DTable* DTable)
607
564
{
608
    /* Check */
609
564
    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */
610
564
    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */
611
612
564
    {   const BYTE* const istart = (const BYTE*) cSrc;
613
564
        BYTE* const ostart = (BYTE*) dst;
614
564
        BYTE* const oend = ostart + dstSize;
615
564
        BYTE* const olimit = oend - 3;
616
564
        const void* const dtPtr = DTable + 1;
617
564
        const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
618
619
        /* Init */
620
564
        BIT_DStream_t bitD1;
621
564
        BIT_DStream_t bitD2;
622
564
        BIT_DStream_t bitD3;
623
564
        BIT_DStream_t bitD4;
624
564
        size_t const length1 = MEM_readLE16(istart);
625
564
        size_t const length2 = MEM_readLE16(istart+2);
626
564
        size_t const length3 = MEM_readLE16(istart+4);
627
564
        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
628
564
        const BYTE* const istart1 = istart + 6;  /* jumpTable */
629
564
        const BYTE* const istart2 = istart1 + length1;
630
564
        const BYTE* const istart3 = istart2 + length2;
631
564
        const BYTE* const istart4 = istart3 + length3;
632
564
        const size_t segmentSize = (dstSize+3) / 4;
633
564
        BYTE* const opStart2 = ostart + segmentSize;
634
564
        BYTE* const opStart3 = opStart2 + segmentSize;
635
564
        BYTE* const opStart4 = opStart3 + segmentSize;
636
564
        BYTE* op1 = ostart;
637
564
        BYTE* op2 = opStart2;
638
564
        BYTE* op3 = opStart3;
639
564
        BYTE* op4 = opStart4;
640
564
        DTableDesc const dtd = HUF_getDTableDesc(DTable);
641
564
        U32 const dtLog = dtd.tableLog;
642
564
        U32 endSignal = 1;
643
644
564
        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
645
557
        if (opStart4 > oend) return ERROR(corruption_detected);      /* overflow */
646
557
        assert(dstSize >= 6); /* validated above */
647
557
        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
648
555
        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
649
553
        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
650
552
        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
651
652
        /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
653
549
        if ((size_t)(oend - op4) >= sizeof(size_t)) {
654
1.09k
            for ( ; (endSignal) & (op4 < olimit) ; ) {
655
549
                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
656
549
                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
657
549
                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
658
549
                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
659
549
                HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
660
549
                HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
661
549
                HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
662
549
                HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
663
549
                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
664
549
                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
665
549
                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
666
549
                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
667
549
                HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
668
549
                HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
669
549
                HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
670
549
                HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
671
549
                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
672
549
                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
673
549
                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
674
549
                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
675
549
            }
676
543
        }
677
678
        /* check corruption */
679
        /* note : should not be necessary : op# advance in lock step, and we control op4.
680
         *        but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */
681
549
        if (op1 > opStart2) return ERROR(corruption_detected);
682
549
        if (op2 > opStart3) return ERROR(corruption_detected);
683
549
        if (op3 > opStart4) return ERROR(corruption_detected);
684
        /* note : op4 supposed already verified within main loop */
685
686
        /* finish bitStreams one by one */
687
549
        HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);
688
549
        HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);
689
549
        HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);
690
549
        HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);
691
692
        /* check */
693
549
        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
694
549
          if (!endCheck) return ERROR(corruption_detected); }
695
696
        /* decoded size */
697
527
        return dstSize;
698
549
    }
699
549
}
700
701
#if HUF_NEED_BMI2_FUNCTION
702
static BMI2_TARGET_ATTRIBUTE
703
size_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
704
564
                    size_t cSrcSize, HUF_DTable const* DTable) {
705
564
    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
706
564
}
707
#endif
708
709
static
710
size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
711
0
                    size_t cSrcSize, HUF_DTable const* DTable) {
712
0
    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
713
0
}
714
715
#if ZSTD_ENABLE_ASM_X86_64_BMI2
716
717
HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;
718
719
#endif
720
721
static HUF_FAST_BMI2_ATTRS
722
void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)
723
0
{
724
0
    U64 bits[4];
725
0
    BYTE const* ip[4];
726
0
    BYTE* op[4];
727
0
    U16 const* const dtable = (U16 const*)args->dt;
728
0
    BYTE* const oend = args->oend;
729
0
    BYTE const* const ilowest = args->ilowest;
730
731
    /* Copy the arguments to local variables */
732
0
    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
733
0
    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));
734
0
    ZSTD_memcpy(&op, &args->op, sizeof(op));
735
736
0
    assert(MEM_isLittleEndian());
737
0
    assert(!MEM_32bits());
738
739
0
    for (;;) {
740
0
        BYTE* olimit;
741
0
        int stream;
742
743
        /* Assert loop preconditions */
744
0
#ifndef NDEBUG
745
0
        for (stream = 0; stream < 4; ++stream) {
746
0
            assert(op[stream] <= (stream == 3 ? oend : op[stream + 1]));
747
0
            assert(ip[stream] >= ilowest);
748
0
        }
749
0
#endif
750
        /* Compute olimit */
751
0
        {
752
            /* Each iteration produces 5 output symbols per stream */
753
0
            size_t const oiters = (size_t)(oend - op[3]) / 5;
754
            /* Each iteration consumes up to 11 bits * 5 = 55 bits < 7 bytes
755
             * per stream.
756
             */
757
0
            size_t const iiters = (size_t)(ip[0] - ilowest) / 7;
758
            /* We can safely run iters iterations before running bounds checks */
759
0
            size_t const iters = MIN(oiters, iiters);
760
0
            size_t const symbols = iters * 5;
761
762
            /* We can simply check that op[3] < olimit, instead of checking all
763
             * of our bounds, since we can't hit the other bounds until we've run
764
             * iters iterations, which only happens when op[3] == olimit.
765
             */
766
0
            olimit = op[3] + symbols;
767
768
            /* Exit fast decoding loop once we reach the end. */
769
0
            if (op[3] == olimit)
770
0
                break;
771
772
            /* Exit the decoding loop if any input pointer has crossed the
773
             * previous one. This indicates corruption, and a precondition
774
             * to our loop is that ip[i] >= ip[0].
775
             */
776
0
            for (stream = 1; stream < 4; ++stream) {
777
0
                if (ip[stream] < ip[stream - 1])
778
0
                    goto _out;
779
0
            }
780
0
        }
781
782
0
#ifndef NDEBUG
783
0
        for (stream = 1; stream < 4; ++stream) {
784
0
            assert(ip[stream] >= ip[stream - 1]);
785
0
        }
786
0
#endif
787
788
0
#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol)        \
789
0
    do {                                               \
790
0
        U64 const index = bits[(_stream)] >> 53;       \
791
0
        U16 const entry = dtable[index];               \
792
0
        bits[(_stream)] <<= entry & 0x3F;              \
793
0
        op[(_stream)][(_symbol)] = (BYTE)(entry >> 8); \
794
0
    } while (0)
795
796
0
#define HUF_5X1_RELOAD_STREAM(_stream)                              \
797
0
    do {                                                            \
798
0
        U64 const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
799
0
        U64 const nbBits = ctz & 7;                                 \
800
0
        U64 const nbBytes = ctz >> 3;                               \
801
0
        op[(_stream)] += 5;                                         \
802
0
        ip[(_stream)] -= nbBytes;                                   \
803
0
        bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \
804
0
        bits[(_stream)] <<= nbBits;                                 \
805
0
    } while (0)
806
807
        /* Manually unroll the loop because compilers don't consistently
808
         * unroll the inner loops, which destroys performance.
809
         */
810
0
        do {
811
            /* Decode 5 symbols in each of the 4 streams */
812
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 0);
813
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 1);
814
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 2);
815
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 3);
816
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4);
817
818
            /* Reload each of the 4 the bitstreams */
819
0
            HUF_4X_FOR_EACH_STREAM(HUF_5X1_RELOAD_STREAM);
820
0
        } while (op[3] < olimit);
821
822
0
#undef HUF_4X1_DECODE_SYMBOL
823
0
#undef HUF_5X1_RELOAD_STREAM
824
0
    }
825
826
0
_out:
827
828
    /* Save the final values of each of the state variables back to args. */
829
0
    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
830
0
    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));
831
0
    ZSTD_memcpy(&args->op, &op, sizeof(op));
832
0
}
833
834
/**
835
 * @returns @p dstSize on success (>= 6)
836
 *          0 if the fallback implementation should be used
837
 *          An error if an error occurred
838
 */
839
static HUF_FAST_BMI2_ATTRS
840
size_t
841
HUF_decompress4X1_usingDTable_internal_fast(
842
          void* dst,  size_t dstSize,
843
    const void* cSrc, size_t cSrcSize,
844
    const HUF_DTable* DTable,
845
    HUF_DecompressFastLoopFn loopFn)
846
1.92k
{
847
1.92k
    void const* dt = DTable + 1;
848
1.92k
    BYTE const* const ilowest = (BYTE const*)cSrc;
849
1.92k
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
850
1.92k
    HUF_DecompressFastArgs args;
851
1.92k
    {   size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
852
1.92k
        FORWARD_IF_ERROR(ret, "Failed to init fast loop args");
853
1.92k
        if (ret == 0)
854
564
            return 0;
855
1.92k
    }
856
857
1.92k
    assert(args.ip[0] >= args.ilowest);
858
1.36k
    loopFn(&args);
859
860
    /* Our loop guarantees that ip[] >= ilowest and that we haven't
861
    * overwritten any op[].
862
    */
863
1.36k
    assert(args.ip[0] >= ilowest);
864
1.36k
    assert(args.ip[0] >= ilowest);
865
1.36k
    assert(args.ip[1] >= ilowest);
866
1.36k
    assert(args.ip[2] >= ilowest);
867
1.36k
    assert(args.ip[3] >= ilowest);
868
1.36k
    assert(args.op[3] <= oend);
869
870
1.36k
    assert(ilowest == args.ilowest);
871
1.36k
    assert(ilowest + 6 == args.iend[0]);
872
1.36k
    (void)ilowest;
873
874
    /* finish bit streams one by one. */
875
1.36k
    {   size_t const segmentSize = (dstSize+3) / 4;
876
1.36k
        BYTE* segmentEnd = (BYTE*)dst;
877
1.36k
        int i;
878
6.78k
        for (i = 0; i < 4; ++i) {
879
5.43k
            BIT_DStream_t bit;
880
5.43k
            if (segmentSize <= (size_t)(oend - segmentEnd))
881
4.35k
                segmentEnd += segmentSize;
882
1.08k
            else
883
1.08k
                segmentEnd = oend;
884
5.43k
            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
885
            /* Decompress and validate that we've produced exactly the expected length. */
886
5.42k
            args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG);
887
5.42k
            if (args.op[i] != segmentEnd) return ERROR(corruption_detected);
888
5.42k
        }
889
1.36k
    }
890
891
    /* decoded size */
892
1.36k
    assert(dstSize != 0);
893
1.35k
    return dstSize;
894
1.35k
}
895
896
HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
897
898
static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
899
                    size_t cSrcSize, HUF_DTable const* DTable, int flags)
900
1.92k
{
901
1.92k
    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default;
902
1.92k
    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;
903
904
1.92k
#if DYNAMIC_BMI2
905
1.92k
    if (flags & HUF_flags_bmi2) {
906
1.92k
        fallbackFn = HUF_decompress4X1_usingDTable_internal_bmi2;
907
1.92k
# if ZSTD_ENABLE_ASM_X86_64_BMI2
908
1.92k
        if (!(flags & HUF_flags_disableAsm)) {
909
1.92k
            loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;
910
1.92k
        }
911
1.92k
# endif
912
1.92k
    } else {
913
0
        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
914
0
    }
915
1.92k
#endif
916
917
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
918
    if (!(flags & HUF_flags_disableAsm)) {
919
        loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;
920
    }
921
#endif
922
923
1.92k
    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {
924
1.92k
        size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
925
1.92k
        if (ret != 0)
926
1.36k
            return ret;
927
1.92k
    }
928
564
    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
929
1.92k
}
930
931
static size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
932
                                   const void* cSrc, size_t cSrcSize,
933
                                   void* workSpace, size_t wkspSize, int flags)
934
1.33k
{
935
1.33k
    const BYTE* ip = (const BYTE*) cSrc;
936
937
1.33k
    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);
938
1.33k
    if (HUF_isError(hSize)) return hSize;
939
1.32k
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
940
1.32k
    ip += hSize; cSrcSize -= hSize;
941
942
1.32k
    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
943
1.32k
}
944
945
#endif /* HUF_FORCE_DECOMPRESS_X2 */
946
947
948
#ifndef HUF_FORCE_DECOMPRESS_X1
949
950
/* *************************/
951
/* double-symbols decoding */
952
/* *************************/
953
954
typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2;  /* double-symbols decoding */
955
typedef struct { BYTE symbol; } sortedSymbol_t;
956
typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
957
typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
958
959
/**
960
 * Constructs a HUF_DEltX2 in a U32.
961
 */
962
static U32 HUF_buildDEltX2U32(U32 symbol, U32 nbBits, U32 baseSeq, int level)
963
5.05M
{
964
5.05M
    U32 seq;
965
5.05M
    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0);
966
5.05M
    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2);
967
5.05M
    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3);
968
5.05M
    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32));
969
5.05M
    if (MEM_isLittleEndian()) {
970
5.05M
        seq = level == 1 ? symbol : (baseSeq + (symbol << 8));
971
5.05M
        return seq + (nbBits << 16) + ((U32)level << 24);
972
5.05M
    } else {
973
0
        seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol);
974
0
        return (seq << 16) + (nbBits << 8) + (U32)level;
975
0
    }
976
5.05M
}
977
978
/**
979
 * Constructs a HUF_DEltX2.
980
 */
981
static HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level)
982
1.85M
{
983
1.85M
    HUF_DEltX2 DElt;
984
1.85M
    U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
985
1.85M
    DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val));
986
1.85M
    ZSTD_memcpy(&DElt, &val, sizeof(val));
987
1.85M
    return DElt;
988
1.85M
}
989
990
/**
991
 * Constructs 2 HUF_DEltX2s and packs them into a U64.
992
 */
993
static U64 HUF_buildDEltX2U64(U32 symbol, U32 nbBits, U16 baseSeq, int level)
994
3.20M
{
995
3.20M
    U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
996
3.20M
    return (U64)DElt + ((U64)DElt << 32);
997
3.20M
}
998
999
/**
1000
 * Fills the DTable rank with all the symbols from [begin, end) that are each
1001
 * nbBits long.
1002
 *
1003
 * @param DTableRank The start of the rank in the DTable.
1004
 * @param begin The first symbol to fill (inclusive).
1005
 * @param end The last symbol to fill (exclusive).
1006
 * @param nbBits Each symbol is nbBits long.
1007
 * @param tableLog The table log.
1008
 * @param baseSeq If level == 1 { 0 } else { the first level symbol }
1009
 * @param level The level in the table. Must be 1 or 2.
1010
 */
1011
static void HUF_fillDTableX2ForWeight(
1012
    HUF_DEltX2* DTableRank,
1013
    sortedSymbol_t const* begin, sortedSymbol_t const* end,
1014
    U32 nbBits, U32 tableLog,
1015
    U16 baseSeq, int const level)
1016
1.01M
{
1017
1.01M
    U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */);
1018
1.01M
    const sortedSymbol_t* ptr;
1019
1.01M
    assert(level >= 1 && level <= 2);
1020
1.01M
    switch (length) {
1021
703k
    case 1:
1022
2.10M
        for (ptr = begin; ptr != end; ++ptr) {
1023
1.39M
            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
1024
1.39M
            *DTableRank++ = DElt;
1025
1.39M
        }
1026
703k
        break;
1027
165k
    case 2:
1028
619k
        for (ptr = begin; ptr != end; ++ptr) {
1029
454k
            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
1030
454k
            DTableRank[0] = DElt;
1031
454k
            DTableRank[1] = DElt;
1032
454k
            DTableRank += 2;
1033
454k
        }
1034
165k
        break;
1035
69.0k
    case 4:
1036
813k
        for (ptr = begin; ptr != end; ++ptr) {
1037
744k
            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
1038
744k
            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
1039
744k
            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
1040
744k
            DTableRank += 4;
1041
744k
        }
1042
69.0k
        break;
1043
39.6k
    case 8:
1044
1.74M
        for (ptr = begin; ptr != end; ++ptr) {
1045
1.70M
            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
1046
1.70M
            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
1047
1.70M
            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
1048
1.70M
            ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
1049
1.70M
            ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
1050
1.70M
            DTableRank += 8;
1051
1.70M
        }
1052
39.6k
        break;
1053
39.8k
    default:
1054
95.9k
        for (ptr = begin; ptr != end; ++ptr) {
1055
56.1k
            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
1056
56.1k
            HUF_DEltX2* const DTableRankEnd = DTableRank + length;
1057
298k
            for (; DTableRank != DTableRankEnd; DTableRank += 8) {
1058
242k
                ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
1059
242k
                ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
1060
242k
                ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
1061
242k
                ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
1062
242k
            }
1063
56.1k
        }
1064
39.8k
        break;
1065
1.01M
    }
1066
1.01M
}
1067
1068
/* HUF_fillDTableX2Level2() :
1069
 * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
1070
static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 consumedBits,
1071
                           const U32* rankVal, const int minWeight, const int maxWeight1,
1072
                           const sortedSymbol_t* sortedSymbols, U32 const* rankStart,
1073
                           U32 nbBitsBaseline, U16 baseSeq)
1074
705k
{
1075
    /* Fill skipped values (all positions up to rankVal[minWeight]).
1076
     * These are positions only get a single symbol because the combined weight
1077
     * is too large.
1078
     */
1079
705k
    if (minWeight>1) {
1080
701k
        U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */);
1081
701k
        U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1);
1082
701k
        int const skipSize = rankVal[minWeight];
1083
701k
        assert(length > 1);
1084
701k
        assert((U32)skipSize < length);
1085
701k
        switch (length) {
1086
20.3k
        case 2:
1087
20.3k
            assert(skipSize == 1);
1088
20.3k
            ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2));
1089
20.3k
            break;
1090
153k
        case 4:
1091
153k
            assert(skipSize <= 4);
1092
153k
            ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2));
1093
153k
            ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2));
1094
153k
            break;
1095
527k
        default:
1096
527k
            {
1097
527k
                int i;
1098
1.30M
                for (i = 0; i < skipSize; i += 8) {
1099
779k
                    ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2));
1100
779k
                    ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2));
1101
779k
                    ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2));
1102
779k
                    ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2));
1103
779k
                }
1104
527k
            }
1105
701k
        }
1106
701k
    }
1107
1108
    /* Fill each of the second level symbols by weight. */
1109
705k
    {
1110
705k
        int w;
1111
1.69M
        for (w = minWeight; w < maxWeight1; ++w) {
1112
990k
            int const begin = rankStart[w];
1113
990k
            int const end = rankStart[w+1];
1114
990k
            U32 const nbBits = nbBitsBaseline - w;
1115
990k
            U32 const totalBits = nbBits + consumedBits;
1116
990k
            HUF_fillDTableX2ForWeight(
1117
990k
                DTable + rankVal[w],
1118
990k
                sortedSymbols + begin, sortedSymbols + end,
1119
990k
                totalBits, targetLog,
1120
990k
                baseSeq, /* level */ 2);
1121
990k
        }
1122
705k
    }
1123
705k
}
1124
1125
static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
1126
                           const sortedSymbol_t* sortedList,
1127
                           const U32* rankStart, rankValCol_t* rankValOrigin, const U32 maxWeight,
1128
                           const U32 nbBitsBaseline)
1129
13.0k
{
1130
13.0k
    U32* const rankVal = rankValOrigin[0];
1131
13.0k
    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */
1132
13.0k
    const U32 minBits  = nbBitsBaseline - maxWeight;
1133
13.0k
    int w;
1134
13.0k
    int const wEnd = (int)maxWeight + 1;
1135
1136
    /* Fill DTable in order of weight. */
1137
88.4k
    for (w = 1; w < wEnd; ++w) {
1138
75.4k
        int const begin = (int)rankStart[w];
1139
75.4k
        int const end = (int)rankStart[w+1];
1140
75.4k
        U32 const nbBits = nbBitsBaseline - w;
1141
1142
75.4k
        if (targetLog-nbBits >= minBits) {
1143
            /* Enough room for a second symbol. */
1144
48.4k
            int start = rankVal[w];
1145
48.4k
            U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */);
1146
48.4k
            int minWeight = nbBits + scaleLog;
1147
48.4k
            int s;
1148
48.4k
            if (minWeight < 1) minWeight = 1;
1149
            /* Fill the DTable for every symbol of weight w.
1150
             * These symbols get at least 1 second symbol.
1151
             */
1152
753k
            for (s = begin; s != end; ++s) {
1153
705k
                HUF_fillDTableX2Level2(
1154
705k
                    DTable + start, targetLog, nbBits,
1155
705k
                    rankValOrigin[nbBits], minWeight, wEnd,
1156
705k
                    sortedList, rankStart,
1157
705k
                    nbBitsBaseline, sortedList[s].symbol);
1158
705k
                start += length;
1159
705k
            }
1160
48.4k
        } else {
1161
            /* Only a single symbol. */
1162
26.9k
            HUF_fillDTableX2ForWeight(
1163
26.9k
                DTable + rankVal[w],
1164
26.9k
                sortedList + begin, sortedList + end,
1165
26.9k
                nbBits, targetLog,
1166
26.9k
                /* baseSeq */ 0, /* level */ 1);
1167
26.9k
        }
1168
75.4k
    }
1169
13.0k
}
1170
1171
typedef struct {
1172
    rankValCol_t rankVal[HUF_TABLELOG_MAX];
1173
    U32 rankStats[HUF_TABLELOG_MAX + 1];
1174
    U32 rankStart0[HUF_TABLELOG_MAX + 3];
1175
    sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];
1176
    BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];
1177
    U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
1178
} HUF_ReadDTableX2_Workspace;
1179
1180
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
1181
                       const void* src, size_t srcSize,
1182
                             void* workSpace, size_t wkspSize, int flags)
1183
13.0k
{
1184
13.0k
    U32 tableLog, maxW, nbSymbols;
1185
13.0k
    DTableDesc dtd = HUF_getDTableDesc(DTable);
1186
13.0k
    U32 maxTableLog = dtd.maxTableLog;
1187
13.0k
    size_t iSize;
1188
13.0k
    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */
1189
13.0k
    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
1190
13.0k
    U32 *rankStart;
1191
1192
13.0k
    HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;
1193
1194
13.0k
    if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);
1195
1196
13.0k
    rankStart = wksp->rankStart0 + 1;
1197
13.0k
    ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));
1198
13.0k
    ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));
1199
1200
13.0k
    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */
1201
13.0k
    if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
1202
    /* ZSTD_memset(weightList, 0, sizeof(weightList)); */  /* is not necessary, even though some analyzer complain ... */
1203
1204
13.0k
    iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), flags);
1205
13.0k
    if (HUF_isError(iSize)) return iSize;
1206
1207
    /* check result */
1208
13.0k
    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */
1209
13.0k
    if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG;
1210
1211
    /* find maxWeight */
1212
56.9k
    for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */
1213
1214
    /* Get start index of each weight */
1215
13.0k
    {   U32 w, nextRankStart = 0;
1216
88.4k
        for (w=1; w<maxW+1; w++) {
1217
75.4k
            U32 curr = nextRankStart;
1218
75.4k
            nextRankStart += wksp->rankStats[w];
1219
75.4k
            rankStart[w] = curr;
1220
75.4k
        }
1221
13.0k
        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
1222
13.0k
        rankStart[maxW+1] = nextRankStart;
1223
13.0k
    }
1224
1225
    /* sort symbols by weight */
1226
13.0k
    {   U32 s;
1227
3.22M
        for (s=0; s<nbSymbols; s++) {
1228
3.20M
            U32 const w = wksp->weightList[s];
1229
3.20M
            U32 const r = rankStart[w]++;
1230
3.20M
            wksp->sortedSymbol[r].symbol = (BYTE)s;
1231
3.20M
        }
1232
13.0k
        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
1233
13.0k
    }
1234
1235
    /* Build rankVal */
1236
13.0k
    {   U32* const rankVal0 = wksp->rankVal[0];
1237
13.0k
        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */
1238
13.0k
            U32 nextRankVal = 0;
1239
13.0k
            U32 w;
1240
88.4k
            for (w=1; w<maxW+1; w++) {
1241
75.4k
                U32 curr = nextRankVal;
1242
75.4k
                nextRankVal += wksp->rankStats[w] << (w+rescale);
1243
75.4k
                rankVal0[w] = curr;
1244
75.4k
        }   }
1245
13.0k
        {   U32 const minBits = tableLog+1 - maxW;
1246
13.0k
            U32 consumed;
1247
62.8k
            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
1248
49.8k
                U32* const rankValPtr = wksp->rankVal[consumed];
1249
49.8k
                U32 w;
1250
413k
                for (w = 1; w < maxW+1; w++) {
1251
364k
                    rankValPtr[w] = rankVal0[w] >> consumed;
1252
364k
    }   }   }   }
1253
1254
13.0k
    HUF_fillDTableX2(dt, maxTableLog,
1255
13.0k
                   wksp->sortedSymbol,
1256
13.0k
                   wksp->rankStart0, wksp->rankVal, maxW,
1257
13.0k
                   tableLog+1);
1258
1259
13.0k
    dtd.tableLog = (BYTE)maxTableLog;
1260
13.0k
    dtd.tableType = 1;
1261
13.0k
    ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
1262
13.0k
    return iSize;
1263
13.0k
}
1264
1265
1266
FORCE_INLINE_TEMPLATE U32
1267
HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
1268
809k
{
1269
809k
    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
1270
809k
    ZSTD_memcpy(op, &dt[val].sequence, 2);
1271
809k
    BIT_skipBits(DStream, dt[val].nbBits);
1272
809k
    return dt[val].length;
1273
809k
}
1274
1275
FORCE_INLINE_TEMPLATE U32
1276
HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
1277
4.24k
{
1278
4.24k
    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
1279
4.24k
    ZSTD_memcpy(op, &dt[val].sequence, 1);
1280
4.24k
    if (dt[val].length==1) {
1281
2.69k
        BIT_skipBits(DStream, dt[val].nbBits);
1282
2.69k
    } else {
1283
1.54k
        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
1284
606
            BIT_skipBits(DStream, dt[val].nbBits);
1285
606
            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
1286
                /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
1287
201
                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
1288
606
        }
1289
1.54k
    }
1290
4.24k
    return 1;
1291
4.24k
}
1292
1293
#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
1294
793k
    do { ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); } while (0)
1295
1296
#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr)                     \
1297
5.27k
    do {                                                           \
1298
5.27k
        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12))                \
1299
5.27k
            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \
1300
5.27k
    } while (0)
1301
1302
#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr)                     \
1303
10.5k
    do {                                                           \
1304
10.5k
        if (MEM_64bits())                                          \
1305
10.5k
            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \
1306
10.5k
    } while (0)
1307
1308
HINT_INLINE size_t
1309
HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
1310
                const HUF_DEltX2* const dt, const U32 dtLog)
1311
5.64k
{
1312
5.64k
    BYTE* const pStart = p;
1313
1314
    /* up to 8 symbols at a time */
1315
5.64k
    if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) {
1316
3.13k
        if (dtLog <= 11 && MEM_64bits()) {
1317
            /* up to 10 symbols at a time */
1318
30.7k
            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) {
1319
27.6k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1320
27.6k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1321
27.6k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1322
27.6k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1323
27.6k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1324
27.6k
            }
1325
3.08k
        } else {
1326
            /* up to 8 symbols at a time */
1327
960
            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
1328
916
                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
1329
916
                HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
1330
916
                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
1331
916
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1332
916
            }
1333
44
        }
1334
3.13k
    } else {
1335
2.51k
        BIT_reloadDStream(bitDPtr);
1336
2.51k
    }
1337
1338
    /* closer to end : up to 2 symbols at a time */
1339
5.64k
    if ((size_t)(pEnd - p) >= 2) {
1340
9.42k
        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
1341
5.48k
            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1342
1343
648k
        while (p <= pEnd-2)
1344
644k
            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
1345
3.93k
    }
1346
1347
5.64k
    if (p < pEnd)
1348
4.24k
        p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
1349
1350
5.64k
    return p-pStart;
1351
5.64k
}
1352
1353
FORCE_INLINE_TEMPLATE size_t
1354
HUF_decompress1X2_usingDTable_internal_body(
1355
          void* dst,  size_t dstSize,
1356
    const void* cSrc, size_t cSrcSize,
1357
    const HUF_DTable* DTable)
1358
1.67k
{
1359
1.67k
    BIT_DStream_t bitD;
1360
1361
    /* Init */
1362
1.67k
    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
1363
1364
    /* decode */
1365
1.67k
    {   BYTE* const ostart = (BYTE*) dst;
1366
1.67k
        BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)dstSize);
1367
1.67k
        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */
1368
1.67k
        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
1369
1.67k
        DTableDesc const dtd = HUF_getDTableDesc(DTable);
1370
1.67k
        HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);
1371
1.67k
    }
1372
1373
    /* check */
1374
1.67k
    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
1375
1376
    /* decoded size */
1377
1.64k
    return dstSize;
1378
1.67k
}
1379
1380
/* HUF_decompress4X2_usingDTable_internal_body():
1381
 * Conditions:
1382
 * @dstSize >= 6
1383
 */
1384
FORCE_INLINE_TEMPLATE size_t
1385
HUF_decompress4X2_usingDTable_internal_body(
1386
          void* dst,  size_t dstSize,
1387
    const void* cSrc, size_t cSrcSize,
1388
    const HUF_DTable* DTable)
1389
86
{
1390
86
    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
1391
86
    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */
1392
1393
86
    {   const BYTE* const istart = (const BYTE*) cSrc;
1394
86
        BYTE* const ostart = (BYTE*) dst;
1395
86
        BYTE* const oend = ostart + dstSize;
1396
86
        BYTE* const olimit = oend - (sizeof(size_t)-1);
1397
86
        const void* const dtPtr = DTable+1;
1398
86
        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
1399
1400
        /* Init */
1401
86
        BIT_DStream_t bitD1;
1402
86
        BIT_DStream_t bitD2;
1403
86
        BIT_DStream_t bitD3;
1404
86
        BIT_DStream_t bitD4;
1405
86
        size_t const length1 = MEM_readLE16(istart);
1406
86
        size_t const length2 = MEM_readLE16(istart+2);
1407
86
        size_t const length3 = MEM_readLE16(istart+4);
1408
86
        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
1409
86
        const BYTE* const istart1 = istart + 6;  /* jumpTable */
1410
86
        const BYTE* const istart2 = istart1 + length1;
1411
86
        const BYTE* const istart3 = istart2 + length2;
1412
86
        const BYTE* const istart4 = istart3 + length3;
1413
86
        size_t const segmentSize = (dstSize+3) / 4;
1414
86
        BYTE* const opStart2 = ostart + segmentSize;
1415
86
        BYTE* const opStart3 = opStart2 + segmentSize;
1416
86
        BYTE* const opStart4 = opStart3 + segmentSize;
1417
86
        BYTE* op1 = ostart;
1418
86
        BYTE* op2 = opStart2;
1419
86
        BYTE* op3 = opStart3;
1420
86
        BYTE* op4 = opStart4;
1421
86
        U32 endSignal = 1;
1422
86
        DTableDesc const dtd = HUF_getDTableDesc(DTable);
1423
86
        U32 const dtLog = dtd.tableLog;
1424
1425
86
        if (length4 > cSrcSize) return ERROR(corruption_detected);  /* overflow */
1426
82
        if (opStart4 > oend) return ERROR(corruption_detected);     /* overflow */
1427
82
        assert(dstSize >= 6 /* validated above */);
1428
82
        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
1429
78
        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
1430
73
        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
1431
72
        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
1432
1433
        /* 16-32 symbols per loop (4-8 symbols per stream) */
1434
71
        if ((size_t)(oend - op4) >= sizeof(size_t)) {
1435
1.14k
            for ( ; (endSignal) & (op4 < olimit); ) {
1436
1.09k
#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
1437
1.09k
                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
1438
1.09k
                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
1439
1.09k
                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
1440
1.09k
                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
1441
1.09k
                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
1442
1.09k
                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
1443
1.09k
                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
1444
1.09k
                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
1445
1.09k
                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
1446
1.09k
                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
1447
1.09k
                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
1448
1.09k
                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
1449
1.09k
                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
1450
1.09k
                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
1451
1.09k
                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
1452
1.09k
                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
1453
1.09k
                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
1454
1.09k
                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
1455
1.09k
                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
1456
1.09k
                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
1457
#else
1458
                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
1459
                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
1460
                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
1461
                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
1462
                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
1463
                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
1464
                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
1465
                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
1466
                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
1467
                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
1468
                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
1469
                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
1470
                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
1471
                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
1472
                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
1473
                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
1474
                endSignal = (U32)LIKELY((U32)
1475
                            (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
1476
                        & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
1477
                        & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
1478
                        & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
1479
#endif
1480
1.09k
            }
1481
57
        }
1482
1483
        /* check corruption */
1484
71
        if (op1 > opStart2) return ERROR(corruption_detected);
1485
70
        if (op2 > opStart3) return ERROR(corruption_detected);
1486
69
        if (op3 > opStart4) return ERROR(corruption_detected);
1487
        /* note : op4 already verified within main loop */
1488
1489
        /* finish bitStreams one by one */
1490
68
        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
1491
68
        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
1492
68
        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
1493
68
        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);
1494
1495
        /* check */
1496
68
        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
1497
68
          if (!endCheck) return ERROR(corruption_detected); }
1498
1499
        /* decoded size */
1500
0
        return dstSize;
1501
68
    }
1502
68
}
1503
1504
#if HUF_NEED_BMI2_FUNCTION
1505
static BMI2_TARGET_ATTRIBUTE
1506
size_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
1507
86
                    size_t cSrcSize, HUF_DTable const* DTable) {
1508
86
    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
1509
86
}
1510
#endif
1511
1512
static
1513
size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
1514
0
                    size_t cSrcSize, HUF_DTable const* DTable) {
1515
0
    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
1516
0
}
1517
1518
#if ZSTD_ENABLE_ASM_X86_64_BMI2
1519
1520
HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;
1521
1522
#endif
1523
1524
static HUF_FAST_BMI2_ATTRS
1525
void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)
1526
0
{
1527
0
    U64 bits[4];
1528
0
    BYTE const* ip[4];
1529
0
    BYTE* op[4];
1530
0
    BYTE* oend[4];
1531
0
    HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt;
1532
0
    BYTE const* const ilowest = args->ilowest;
1533
1534
    /* Copy the arguments to local registers. */
1535
0
    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
1536
0
    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));
1537
0
    ZSTD_memcpy(&op, &args->op, sizeof(op));
1538
1539
0
    oend[0] = op[1];
1540
0
    oend[1] = op[2];
1541
0
    oend[2] = op[3];
1542
0
    oend[3] = args->oend;
1543
1544
0
    assert(MEM_isLittleEndian());
1545
0
    assert(!MEM_32bits());
1546
1547
0
    for (;;) {
1548
0
        BYTE* olimit;
1549
0
        int stream;
1550
1551
        /* Assert loop preconditions */
1552
0
#ifndef NDEBUG
1553
0
        for (stream = 0; stream < 4; ++stream) {
1554
0
            assert(op[stream] <= oend[stream]);
1555
0
            assert(ip[stream] >= ilowest);
1556
0
        }
1557
0
#endif
1558
        /* Compute olimit */
1559
0
        {
1560
            /* Each loop does 5 table lookups for each of the 4 streams.
1561
             * Each table lookup consumes up to 11 bits of input, and produces
1562
             * up to 2 bytes of output.
1563
             */
1564
            /* We can consume up to 7 bytes of input per iteration per stream.
1565
             * We also know that each input pointer is >= ip[0]. So we can run
1566
             * iters loops before running out of input.
1567
             */
1568
0
            size_t iters = (size_t)(ip[0] - ilowest) / 7;
1569
            /* Each iteration can produce up to 10 bytes of output per stream.
1570
             * Each output stream my advance at different rates. So take the
1571
             * minimum number of safe iterations among all the output streams.
1572
             */
1573
0
            for (stream = 0; stream < 4; ++stream) {
1574
0
                size_t const oiters = (size_t)(oend[stream] - op[stream]) / 10;
1575
0
                iters = MIN(iters, oiters);
1576
0
            }
1577
1578
            /* Each iteration produces at least 5 output symbols. So until
1579
             * op[3] crosses olimit, we know we haven't executed iters
1580
             * iterations yet. This saves us maintaining an iters counter,
1581
             * at the expense of computing the remaining # of iterations
1582
             * more frequently.
1583
             */
1584
0
            olimit = op[3] + (iters * 5);
1585
1586
            /* Exit the fast decoding loop once we reach the end. */
1587
0
            if (op[3] == olimit)
1588
0
                break;
1589
1590
            /* Exit the decoding loop if any input pointer has crossed the
1591
             * previous one. This indicates corruption, and a precondition
1592
             * to our loop is that ip[i] >= ip[0].
1593
             */
1594
0
            for (stream = 1; stream < 4; ++stream) {
1595
0
                if (ip[stream] < ip[stream - 1])
1596
0
                    goto _out;
1597
0
            }
1598
0
        }
1599
1600
0
#ifndef NDEBUG
1601
0
        for (stream = 1; stream < 4; ++stream) {
1602
0
            assert(ip[stream] >= ip[stream - 1]);
1603
0
        }
1604
0
#endif
1605
1606
0
#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3)               \
1607
0
    do {                                                       \
1608
0
        if ((_decode3) || (_stream) != 3) {                    \
1609
0
            U64 const index = bits[(_stream)] >> 53;           \
1610
0
            size_t const entry = MEM_readLE32(&dtable[index]); \
1611
0
            MEM_write16(op[(_stream)], (U16)entry);            \
1612
0
            bits[(_stream)] <<= (entry >> 16) & 0x3F;          \
1613
0
            op[(_stream)] += entry >> 24;                      \
1614
0
        }                                                      \
1615
0
    } while (0)
1616
1617
0
#define HUF_5X2_RELOAD_STREAM(_stream, _decode3)                        \
1618
0
    do {                                                                \
1619
0
        if (_decode3) HUF_4X2_DECODE_SYMBOL(3, 1);                      \
1620
0
        {                                                               \
1621
0
            U64 const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
1622
0
            U64 const nbBits = ctz & 7;                                 \
1623
0
            U64 const nbBytes = ctz >> 3;                               \
1624
0
            ip[(_stream)] -= nbBytes;                                   \
1625
0
            bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \
1626
0
            bits[(_stream)] <<= nbBits;                                 \
1627
0
        }                                                               \
1628
0
    } while (0)
1629
1630
#if defined(__aarch64__)
1631
#  define HUF_4X2_4WAY 1
1632
#else
1633
0
#  define HUF_4X2_4WAY 0
1634
0
#endif
1635
0
#define HUF_4X2_3WAY !HUF_4X2_4WAY
1636
1637
        /* Manually unroll the loop because compilers don't consistently
1638
         * unroll the inner loops, which destroys performance.
1639
         */
1640
0
        do {
1641
            /* Decode 5 symbols from each of the first 3 or 4 streams.
1642
             * In the 3-way case the final stream will be decoded during
1643
             * the reload phase to reduce register pressure.
1644
             */
1645
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
1646
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
1647
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
1648
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
1649
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);
1650
1651
            /* In the 3-way case decode one symbol from the final stream. */
1652
0
            HUF_4X2_DECODE_SYMBOL(3, HUF_4X2_3WAY);
1653
1654
            /* In the 3-way case decode 4 symbols from the final stream &
1655
             * reload bitstreams. The final stream is reloaded last, meaning
1656
             * that all 5 symbols are decoded from the final stream before
1657
             * it is reloaded.
1658
             */
1659
0
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_5X2_RELOAD_STREAM, HUF_4X2_3WAY);
1660
0
        } while (op[3] < olimit);
1661
0
    }
1662
1663
0
#undef HUF_4X2_DECODE_SYMBOL
1664
0
#undef HUF_5X2_RELOAD_STREAM
1665
1666
0
_out:
1667
1668
    /* Save the final values of each of the state variables back to args. */
1669
0
    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
1670
0
    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));
1671
0
    ZSTD_memcpy(&args->op, &op, sizeof(op));
1672
0
}
1673
1674
1675
static HUF_FAST_BMI2_ATTRS size_t
1676
HUF_decompress4X2_usingDTable_internal_fast(
1677
          void* dst,  size_t dstSize,
1678
    const void* cSrc, size_t cSrcSize,
1679
    const HUF_DTable* DTable,
1680
1.02k
    HUF_DecompressFastLoopFn loopFn) {
1681
1.02k
    void const* dt = DTable + 1;
1682
1.02k
    const BYTE* const ilowest = (const BYTE*)cSrc;
1683
1.02k
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
1684
1.02k
    HUF_DecompressFastArgs args;
1685
1.02k
    {
1686
1.02k
        size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
1687
1.02k
        FORWARD_IF_ERROR(ret, "Failed to init asm args");
1688
1.01k
        if (ret == 0)
1689
86
            return 0;
1690
1.01k
    }
1691
1692
1.01k
    assert(args.ip[0] >= args.ilowest);
1693
930
    loopFn(&args);
1694
1695
    /* note : op4 already verified within main loop */
1696
930
    assert(args.ip[0] >= ilowest);
1697
930
    assert(args.ip[1] >= ilowest);
1698
930
    assert(args.ip[2] >= ilowest);
1699
930
    assert(args.ip[3] >= ilowest);
1700
930
    assert(args.op[3] <= oend);
1701
1702
930
    assert(ilowest == args.ilowest);
1703
930
    assert(ilowest + 6 == args.iend[0]);
1704
930
    (void)ilowest;
1705
1706
    /* finish bitStreams one by one */
1707
930
    {
1708
930
        size_t const segmentSize = (dstSize+3) / 4;
1709
930
        BYTE* segmentEnd = (BYTE*)dst;
1710
930
        int i;
1711
4.63k
        for (i = 0; i < 4; ++i) {
1712
3.70k
            BIT_DStream_t bit;
1713
3.70k
            if (segmentSize <= (size_t)(oend - segmentEnd))
1714
3.08k
                segmentEnd += segmentSize;
1715
619
            else
1716
619
                segmentEnd = oend;
1717
3.70k
            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
1718
3.70k
            args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG);
1719
3.70k
            if (args.op[i] != segmentEnd)
1720
0
                return ERROR(corruption_detected);
1721
3.70k
        }
1722
930
    }
1723
1724
    /* decoded size */
1725
922
    return dstSize;
1726
930
}
1727
1728
static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
1729
                    size_t cSrcSize, HUF_DTable const* DTable, int flags)
1730
1.02k
{
1731
1.02k
    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default;
1732
1.02k
    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;
1733
1734
1.02k
#if DYNAMIC_BMI2
1735
1.02k
    if (flags & HUF_flags_bmi2) {
1736
1.02k
        fallbackFn = HUF_decompress4X2_usingDTable_internal_bmi2;
1737
1.02k
# if ZSTD_ENABLE_ASM_X86_64_BMI2
1738
1.02k
        if (!(flags & HUF_flags_disableAsm)) {
1739
1.02k
            loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;
1740
1.02k
        }
1741
1.02k
# endif
1742
1.02k
    } else {
1743
0
        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
1744
0
    }
1745
1.02k
#endif
1746
1747
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
1748
    if (!(flags & HUF_flags_disableAsm)) {
1749
        loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;
1750
    }
1751
#endif
1752
1753
1.02k
    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {
1754
1.02k
        size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
1755
1.02k
        if (ret != 0)
1756
942
            return ret;
1757
1.02k
    }
1758
86
    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
1759
1.02k
}
1760
1761
HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
1762
1763
size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
1764
                                   const void* cSrc, size_t cSrcSize,
1765
                                   void* workSpace, size_t wkspSize, int flags)
1766
0
{
1767
0
    const BYTE* ip = (const BYTE*) cSrc;
1768
1769
0
    size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
1770
0
                                               workSpace, wkspSize, flags);
1771
0
    if (HUF_isError(hSize)) return hSize;
1772
0
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1773
0
    ip += hSize; cSrcSize -= hSize;
1774
1775
0
    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, flags);
1776
0
}
1777
1778
static size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
1779
                                   const void* cSrc, size_t cSrcSize,
1780
                                   void* workSpace, size_t wkspSize, int flags)
1781
679
{
1782
679
    const BYTE* ip = (const BYTE*) cSrc;
1783
1784
679
    size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
1785
679
                                         workSpace, wkspSize, flags);
1786
679
    if (HUF_isError(hSize)) return hSize;
1787
677
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1788
677
    ip += hSize; cSrcSize -= hSize;
1789
1790
677
    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
1791
677
}
1792
1793
#endif /* HUF_FORCE_DECOMPRESS_X1 */
1794
1795
1796
/* ***********************************/
1797
/* Universal decompression selectors */
1798
/* ***********************************/
1799
1800
1801
#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
1802
typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
1803
static const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] =
1804
{
1805
    /* single, double, quad */
1806
    {{0,0}, {1,1}},  /* Q==0 : impossible */
1807
    {{0,0}, {1,1}},  /* Q==1 : impossible */
1808
    {{ 150,216}, { 381,119}},   /* Q == 2 : 12-18% */
1809
    {{ 170,205}, { 514,112}},   /* Q == 3 : 18-25% */
1810
    {{ 177,199}, { 539,110}},   /* Q == 4 : 25-32% */
1811
    {{ 197,194}, { 644,107}},   /* Q == 5 : 32-38% */
1812
    {{ 221,192}, { 735,107}},   /* Q == 6 : 38-44% */
1813
    {{ 256,189}, { 881,106}},   /* Q == 7 : 44-50% */
1814
    {{ 359,188}, {1167,109}},   /* Q == 8 : 50-56% */
1815
    {{ 582,187}, {1570,114}},   /* Q == 9 : 56-62% */
1816
    {{ 688,187}, {1712,122}},   /* Q ==10 : 62-69% */
1817
    {{ 825,186}, {1965,136}},   /* Q ==11 : 69-75% */
1818
    {{ 976,185}, {2131,150}},   /* Q ==12 : 75-81% */
1819
    {{1180,186}, {2070,175}},   /* Q ==13 : 81-87% */
1820
    {{1377,185}, {1731,202}},   /* Q ==14 : 87-93% */
1821
    {{1412,185}, {1695,202}},   /* Q ==15 : 93-99% */
1822
};
1823
#endif
1824
1825
/** HUF_selectDecoder() :
1826
 *  Tells which decoder is likely to decode faster,
1827
 *  based on a set of pre-computed metrics.
1828
 * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
1829
 *  Assumption : 0 < dstSize <= 128 KB */
1830
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
1831
2.01k
{
1832
2.01k
    assert(dstSize > 0);
1833
2.01k
    assert(dstSize <= 128*1024);
1834
#if defined(HUF_FORCE_DECOMPRESS_X1)
1835
    (void)dstSize;
1836
    (void)cSrcSize;
1837
    return 0;
1838
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1839
    (void)dstSize;
1840
    (void)cSrcSize;
1841
    return 1;
1842
#else
1843
    /* decoder timing evaluation */
1844
2.01k
    {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */
1845
2.01k
        U32 const D256 = (U32)(dstSize >> 8);
1846
2.01k
        U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
1847
2.01k
        U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
1848
2.01k
        DTime1 += DTime1 >> 5;  /* small advantage to algorithm using less memory, to reduce cache eviction */
1849
2.01k
        return DTime1 < DTime0;
1850
2.01k
    }
1851
2.01k
#endif
1852
2.01k
}
1853
1854
size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
1855
                                  const void* cSrc, size_t cSrcSize,
1856
                                  void* workSpace, size_t wkspSize, int flags)
1857
0
{
1858
    /* validation checks */
1859
0
    if (dstSize == 0) return ERROR(dstSize_tooSmall);
1860
0
    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
1861
0
    if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
1862
0
    if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
1863
1864
0
    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1865
#if defined(HUF_FORCE_DECOMPRESS_X1)
1866
        (void)algoNb;
1867
        assert(algoNb == 0);
1868
        return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
1869
                                cSrcSize, workSpace, wkspSize, flags);
1870
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1871
        (void)algoNb;
1872
        assert(algoNb == 1);
1873
        return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
1874
                                cSrcSize, workSpace, wkspSize, flags);
1875
#else
1876
0
        return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
1877
0
                                cSrcSize, workSpace, wkspSize, flags):
1878
0
                        HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
1879
0
                                cSrcSize, workSpace, wkspSize, flags);
1880
0
#endif
1881
0
    }
1882
0
}
1883
1884
1885
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)
1886
1.75k
{
1887
1.75k
    DTableDesc const dtd = HUF_getDTableDesc(DTable);
1888
#if defined(HUF_FORCE_DECOMPRESS_X1)
1889
    (void)dtd;
1890
    assert(dtd.tableType == 0);
1891
    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1892
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1893
    (void)dtd;
1894
    assert(dtd.tableType == 1);
1895
    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1896
#else
1897
1.75k
    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :
1898
1.75k
                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1899
1.75k
#endif
1900
1.75k
}
1901
1902
#ifndef HUF_FORCE_DECOMPRESS_X2
1903
size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)
1904
4.38k
{
1905
4.38k
    const BYTE* ip = (const BYTE*) cSrc;
1906
1907
4.38k
    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);
1908
4.38k
    if (HUF_isError(hSize)) return hSize;
1909
4.24k
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1910
4.23k
    ip += hSize; cSrcSize -= hSize;
1911
1912
4.23k
    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
1913
4.24k
}
1914
#endif
1915
1916
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)
1917
955
{
1918
955
    DTableDesc const dtd = HUF_getDTableDesc(DTable);
1919
#if defined(HUF_FORCE_DECOMPRESS_X1)
1920
    (void)dtd;
1921
    assert(dtd.tableType == 0);
1922
    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1923
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1924
    (void)dtd;
1925
    assert(dtd.tableType == 1);
1926
    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1927
#else
1928
955
    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :
1929
955
                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1930
955
#endif
1931
955
}
1932
1933
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)
1934
2.01k
{
1935
    /* validation checks */
1936
2.01k
    if (dstSize == 0) return ERROR(dstSize_tooSmall);
1937
2.01k
    if (cSrcSize == 0) return ERROR(corruption_detected);
1938
1939
2.01k
    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1940
#if defined(HUF_FORCE_DECOMPRESS_X1)
1941
        (void)algoNb;
1942
        assert(algoNb == 0);
1943
        return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
1944
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1945
        (void)algoNb;
1946
        assert(algoNb == 1);
1947
        return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
1948
#else
1949
2.01k
        return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags) :
1950
2.01k
                        HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
1951
2.01k
#endif
1952
2.01k
    }
1953
2.01k
}