Coverage Report

Created: 2025-07-23 08:18

/src/zstd/lib/decompress/huf_decompress.c
Line
Count
Source (jump to first uncovered line)
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
3.87k
#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
1.80k
# 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
2.47k
#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
60
    {                                                                       \
114
60
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
115
60
    }                                                                       \
Unexecuted instantiation: huf_decompress.c:HUF_decompress1X2_usingDTable_internal_bmi2
huf_decompress.c:HUF_decompress1X1_usingDTable_internal_bmi2
Line
Count
Source
113
60
    {                                                                       \
114
60
        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
115
60
    }                                                                       \
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
60
    {                                                                       \
120
60
        if (flags & HUF_flags_bmi2) {                                       \
121
60
            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
122
60
        }                                                                   \
123
60
        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
124
60
    }
Unexecuted instantiation: huf_decompress.c:HUF_decompress1X2_usingDTable_internal
huf_decompress.c:HUF_decompress1X1_usingDTable_internal
Line
Count
Source
119
60
    {                                                                       \
120
60
        if (flags & HUF_flags_bmi2) {                                       \
121
60
            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
122
60
        }                                                                   \
123
60
        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
124
60
    }
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
2.55k
{
146
2.55k
    DTableDesc dtd;
147
2.55k
    ZSTD_memcpy(&dtd, table, sizeof(dtd));
148
2.55k
    return dtd;
149
2.55k
}
150
151
1.04k
static size_t HUF_initFastDStream(BYTE const* ip) {
152
1.04k
    BYTE const lastByte = ip[7];
153
1.04k
    size_t const bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;
154
1.04k
    size_t const value = MEM_readLEST(ip) | 1;
155
1.04k
    assert(bitsConsumed <= 8);
156
1.04k
    assert(sizeof(size_t) == 8);
157
1.04k
    return value << bitsConsumed;
158
1.04k
}
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
904
{
194
904
    void const* dt = DTable + 1;
195
904
    U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;
196
197
904
    const BYTE* const istart = (const BYTE*)src;
198
199
904
    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
904
    if (!MEM_isLittleEndian() || MEM_32bits())
205
0
        return 0;
206
207
    /* Avoid nullptr addition */
208
904
    if (dstSize == 0)
209
0
        return 0;
210
904
    assert(dst != NULL);
211
212
    /* strict minimum : jump table + 1 byte per stream */
213
904
    if (srcSize < 10)
214
3
        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
901
    if (dtLog != HUF_DECODER_FAST_TABLELOG)
221
112
        return 0;
222
223
    /* Read the jump table. */
224
789
    {
225
789
        size_t const length1 = MEM_readLE16(istart);
226
789
        size_t const length2 = MEM_readLE16(istart+2);
227
789
        size_t const length3 = MEM_readLE16(istart+4);
228
789
        size_t const length4 = srcSize - (length1 + length2 + length3 + 6);
229
789
        args->iend[0] = istart + 6;  /* jumpTable */
230
789
        args->iend[1] = args->iend[0] + length1;
231
789
        args->iend[2] = args->iend[1] + length2;
232
789
        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
789
        if (length1 < 8 || length2 < 8 || length3 < 8 || length4 < 8)
238
414
            return 0;
239
375
        if (length4 > srcSize) return ERROR(corruption_detected);   /* overflow */
240
375
    }
241
    /* ip[] contains the position that is currently loaded into bits[]. */
242
261
    args->ip[0] = args->iend[1] - sizeof(U64);
243
261
    args->ip[1] = args->iend[2] - sizeof(U64);
244
261
    args->ip[2] = args->iend[3] - sizeof(U64);
245
261
    args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64);
246
247
    /* op[] contains the output pointers. */
248
261
    args->op[0] = (BYTE*)dst;
249
261
    args->op[1] = args->op[0] + (dstSize+3)/4;
250
261
    args->op[2] = args->op[1] + (dstSize+3)/4;
251
261
    args->op[3] = args->op[2] + (dstSize+3)/4;
252
253
    /* No point to call the ASM loop for tiny outputs. */
254
261
    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
260
    args->bits[0] = HUF_initFastDStream(args->ip[0]);
265
260
    args->bits[1] = HUF_initFastDStream(args->ip[1]);
266
260
    args->bits[2] = HUF_initFastDStream(args->ip[2]);
267
260
    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
260
    args->ilowest = istart;
275
276
260
    args->oend = oend;
277
260
    args->dt = dt;
278
279
260
    return 1;
280
261
}
281
282
static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArgs const* args, int stream, BYTE* segmentEnd)
283
883
{
284
    /* Validate that we haven't overwritten. */
285
883
    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
883
    if (args->ip[stream] < args->iend[stream] - 8)
293
117
        return ERROR(corruption_detected);
294
295
    /* Construct the BIT_DStream_t. */
296
766
    assert(sizeof(size_t) == 8);
297
766
    bit->bitContainer = MEM_readLEST(args->ip[stream]);
298
766
    bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]);
299
766
    bit->start = (const char*)args->ilowest;
300
766
    bit->limitPtr = bit->start + sizeof(size_t);
301
766
    bit->ptr = (const char*)args->ip[stream];
302
303
766
    return 0;
304
883
}
305
306
/* Calls X(N) for each stream 0, 1, 2, 3. */
307
#define HUF_4X_FOR_EACH_STREAM(X) \
308
4.41k
    do {                          \
309
4.41k
        X(0);                     \
310
4.41k
        X(1);                     \
311
4.41k
        X(2);                     \
312
4.41k
        X(3);                     \
313
4.41k
    } 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
22.0k
    do {                                        \
318
22.0k
        X(0, (var));                            \
319
22.0k
        X(1, (var));                            \
320
22.0k
        X(2, (var));                            \
321
22.0k
        X(3, (var));                            \
322
22.0k
    } 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
11.5k
static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
337
11.5k
    U64 D4;
338
11.5k
    if (MEM_isLittleEndian()) {
339
11.5k
        D4 = (U64)((symbol << 8) + nbBits);
340
11.5k
    } else {
341
0
        D4 = (U64)(symbol + (nbBits << 8));
342
0
    }
343
11.5k
    assert(D4 < (1U << 16));
344
11.5k
    D4 *= 0x0001000100010001ULL;
345
11.5k
    return D4;
346
11.5k
}
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
383
{
355
383
    if (tableLog > targetTableLog)
356
64
        return tableLog;
357
319
    if (tableLog < targetTableLog) {
358
276
        U32 const scale = targetTableLog - tableLog;
359
276
        U32 s;
360
        /* Increase the weight for all non-zero probability symbols by scale. */
361
37.7k
        for (s = 0; s < nbSymbols; ++s) {
362
37.4k
            huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale);
363
37.4k
        }
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
2.22k
        for (s = targetTableLog; s > scale; --s) {
369
1.95k
            rankVal[s] = rankVal[s - scale];
370
1.95k
        }
371
1.35k
        for (s = scale; s > 0; --s) {
372
1.08k
            rankVal[s] = 0;
373
1.08k
        }
374
276
    }
375
319
    return targetTableLog;
376
383
}
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
557
{
388
557
    U32 tableLog = 0;
389
557
    U32 nbSymbols = 0;
390
557
    size_t iSize;
391
557
    void* const dtPtr = DTable + 1;
392
557
    HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
393
557
    HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;
394
395
557
    DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));
396
557
    if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);
397
398
557
    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
557
    iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), flags);
402
557
    if (HUF_isError(iSize)) return iSize;
403
404
405
    /* Table header */
406
383
    {   DTableDesc dtd = HUF_getDTableDesc(DTable);
407
383
        U32 const maxTableLog = dtd.maxTableLog + 1;
408
383
        U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG);
409
383
        tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog);
410
383
        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */
411
383
        dtd.tableType = 0;
412
383
        dtd.tableLog = (BYTE)tableLog;
413
383
        ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
414
383
    }
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
383
        U32 nextRankStart = 0;
430
383
        int const unroll = 4;
431
383
        int const nLimit = (int)nbSymbols - unroll + 1;
432
5.04k
        for (n=0; n<(int)tableLog+1; n++) {
433
4.66k
            U32 const curr = nextRankStart;
434
4.66k
            nextRankStart += wksp->rankVal[n];
435
4.66k
            wksp->rankStart[n] = curr;
436
4.66k
        }
437
10.7k
        for (n=0; n < nLimit; n += unroll) {
438
10.3k
            int u;
439
51.8k
            for (u=0; u < unroll; ++u) {
440
41.5k
                size_t const w = wksp->huffWeight[n+u];
441
41.5k
                wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);
442
41.5k
            }
443
10.3k
        }
444
771
        for (; n < (int)nbSymbols; ++n) {
445
388
            size_t const w = wksp->huffWeight[n];
446
388
            wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;
447
388
        }
448
383
    }
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
383
    {   U32 w;
457
383
        int symbol = wksp->rankVal[0];
458
383
        int rankStart = 0;
459
4.66k
        for (w=1; w<tableLog+1; ++w) {
460
4.27k
            int const symbolCount = wksp->rankVal[w];
461
4.27k
            int const length = (1 << w) >> 1;
462
4.27k
            int uStart = rankStart;
463
4.27k
            BYTE const nbBits = (BYTE)(tableLog + 1 - w);
464
4.27k
            int s;
465
4.27k
            int u;
466
4.27k
            switch (length) {
467
383
            case 1:
468
755
                for (s=0; s<symbolCount; ++s) {
469
372
                    HUF_DEltX1 D;
470
372
                    D.byte = wksp->symbols[symbol + s];
471
372
                    D.nbBits = nbBits;
472
372
                    dt[uStart] = D;
473
372
                    uStart += 1;
474
372
                }
475
383
                break;
476
383
            case 2:
477
1.16k
                for (s=0; s<symbolCount; ++s) {
478
782
                    HUF_DEltX1 D;
479
782
                    D.byte = wksp->symbols[symbol + s];
480
782
                    D.nbBits = nbBits;
481
782
                    dt[uStart+0] = D;
482
782
                    dt[uStart+1] = D;
483
782
                    uStart += 2;
484
782
                }
485
383
                break;
486
383
            case 4:
487
1.04k
                for (s=0; s<symbolCount; ++s) {
488
660
                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
489
660
                    MEM_write64(dt + uStart, D4);
490
660
                    uStart += 4;
491
660
                }
492
383
                break;
493
383
            case 8:
494
2.99k
                for (s=0; s<symbolCount; ++s) {
495
2.60k
                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
496
2.60k
                    MEM_write64(dt + uStart, D4);
497
2.60k
                    MEM_write64(dt + uStart + 4, D4);
498
2.60k
                    uStart += 8;
499
2.60k
                }
500
383
                break;
501
2.74k
            default:
502
11.0k
                for (s=0; s<symbolCount; ++s) {
503
8.29k
                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
504
63.9k
                    for (u=0; u < length; u += 16) {
505
55.6k
                        MEM_write64(dt + uStart + u + 0, D4);
506
55.6k
                        MEM_write64(dt + uStart + u + 4, D4);
507
55.6k
                        MEM_write64(dt + uStart + u + 8, D4);
508
55.6k
                        MEM_write64(dt + uStart + u + 12, D4);
509
55.6k
                    }
510
8.29k
                    assert(u == length);
511
8.29k
                    uStart += length;
512
8.29k
                }
513
2.74k
                break;
514
4.27k
            }
515
4.27k
            symbol += symbolCount;
516
4.27k
            rankStart += symbolCount * length;
517
4.27k
        }
518
383
    }
519
383
    return iSize;
520
383
}
521
522
FORCE_INLINE_TEMPLATE BYTE
523
HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
524
118k
{
525
118k
    size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
526
118k
    BYTE const c = dt[val].byte;
527
118k
    BIT_skipBits(Dstream, dt[val].nbBits);
528
118k
    return c;
529
118k
}
530
531
#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
532
118k
    do { *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog); } while (0)
533
534
#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)      \
535
13.7k
    do {                                            \
536
13.7k
        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
537
13.7k
            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \
538
13.7k
    } while (0)
539
540
#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr)      \
541
27.4k
    do {                                            \
542
27.4k
        if (MEM_64bits())                           \
543
27.4k
            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \
544
27.4k
    } 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
863
{
549
863
    BYTE* const pStart = p;
550
551
    /* up to 4 symbols at a time */
552
863
    if ((pEnd - p) > 3) {
553
13.3k
        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
554
12.5k
            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
555
12.5k
            HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
556
12.5k
            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
557
12.5k
            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
558
12.5k
        }
559
771
    } else {
560
92
        BIT_reloadDStream(bitDPtr);
561
92
    }
562
563
    /* [0-3] symbols remaining */
564
863
    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
64.1k
    while (p < pEnd)
570
63.3k
        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
571
572
863
    return (size_t)(pEnd-pStart);
573
863
}
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
60
{
581
60
    BYTE* op = (BYTE*)dst;
582
60
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(op, (ptrdiff_t)dstSize);
583
60
    const void* dtPtr = DTable + 1;
584
60
    const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
585
60
    BIT_DStream_t bitD;
586
60
    DTableDesc const dtd = HUF_getDTableDesc(DTable);
587
60
    U32 const dtLog = dtd.tableLog;
588
589
60
    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
590
591
51
    HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);
592
593
51
    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
594
595
4
    return dstSize;
596
51
}
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
171
{
608
    /* Check */
609
171
    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */
610
171
    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */
611
612
171
    {   const BYTE* const istart = (const BYTE*) cSrc;
613
171
        BYTE* const ostart = (BYTE*) dst;
614
171
        BYTE* const oend = ostart + dstSize;
615
171
        BYTE* const olimit = oend - 3;
616
171
        const void* const dtPtr = DTable + 1;
617
171
        const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
618
619
        /* Init */
620
171
        BIT_DStream_t bitD1;
621
171
        BIT_DStream_t bitD2;
622
171
        BIT_DStream_t bitD3;
623
171
        BIT_DStream_t bitD4;
624
171
        size_t const length1 = MEM_readLE16(istart);
625
171
        size_t const length2 = MEM_readLE16(istart+2);
626
171
        size_t const length3 = MEM_readLE16(istart+4);
627
171
        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
628
171
        const BYTE* const istart1 = istart + 6;  /* jumpTable */
629
171
        const BYTE* const istart2 = istart1 + length1;
630
171
        const BYTE* const istart3 = istart2 + length2;
631
171
        const BYTE* const istart4 = istart3 + length3;
632
171
        const size_t segmentSize = (dstSize+3) / 4;
633
171
        BYTE* const opStart2 = ostart + segmentSize;
634
171
        BYTE* const opStart3 = opStart2 + segmentSize;
635
171
        BYTE* const opStart4 = opStart3 + segmentSize;
636
171
        BYTE* op1 = ostart;
637
171
        BYTE* op2 = opStart2;
638
171
        BYTE* op3 = opStart3;
639
171
        BYTE* op4 = opStart4;
640
171
        DTableDesc const dtd = HUF_getDTableDesc(DTable);
641
171
        U32 const dtLog = dtd.tableLog;
642
171
        U32 endSignal = 1;
643
644
171
        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
645
151
        if (opStart4 > oend) return ERROR(corruption_detected);      /* overflow */
646
151
        assert(dstSize >= 6); /* validated above */
647
151
        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
648
139
        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
649
128
        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
650
120
        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
651
652
        /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
653
115
        if ((size_t)(oend - op4) >= sizeof(size_t)) {
654
393
            for ( ; (endSignal) & (op4 < olimit) ; ) {
655
288
                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
656
288
                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
657
288
                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
658
288
                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
659
288
                HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
660
288
                HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
661
288
                HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
662
288
                HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
663
288
                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
664
288
                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
665
288
                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
666
288
                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
667
288
                HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
668
288
                HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
669
288
                HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
670
288
                HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
671
288
                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
672
288
                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
673
288
                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
674
288
                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
675
288
            }
676
105
        }
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
115
        if (op1 > opStart2) return ERROR(corruption_detected);
682
115
        if (op2 > opStart3) return ERROR(corruption_detected);
683
115
        if (op3 > opStart4) return ERROR(corruption_detected);
684
        /* note : op4 supposed already verified within main loop */
685
686
        /* finish bitStreams one by one */
687
115
        HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);
688
115
        HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);
689
115
        HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);
690
115
        HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);
691
692
        /* check */
693
115
        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
694
115
          if (!endCheck) return ERROR(corruption_detected); }
695
696
        /* decoded size */
697
0
        return dstSize;
698
115
    }
699
115
}
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
171
                    size_t cSrcSize, HUF_DTable const* DTable) {
705
171
    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
706
171
}
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
114
{
724
114
    U64 bits[4];
725
114
    BYTE const* ip[4];
726
114
    BYTE* op[4];
727
114
    U16 const* const dtable = (U16 const*)args->dt;
728
114
    BYTE* const oend = args->oend;
729
114
    BYTE const* const ilowest = args->ilowest;
730
731
    /* Copy the arguments to local variables */
732
114
    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
733
114
    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));
734
114
    ZSTD_memcpy(&op, &args->op, sizeof(op));
735
736
114
    assert(MEM_isLittleEndian());
737
114
    assert(!MEM_32bits());
738
739
757
    for (;;) {
740
757
        BYTE* olimit;
741
757
        int stream;
742
743
        /* Assert loop preconditions */
744
757
#ifndef NDEBUG
745
3.78k
        for (stream = 0; stream < 4; ++stream) {
746
3.02k
            assert(op[stream] <= (stream == 3 ? oend : op[stream + 1]));
747
3.02k
            assert(ip[stream] >= ilowest);
748
3.02k
        }
749
757
#endif
750
        /* Compute olimit */
751
757
        {
752
            /* Each iteration produces 5 output symbols per stream */
753
757
            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
757
            size_t const iiters = (size_t)(ip[0] - ilowest) / 7;
758
            /* We can safely run iters iterations before running bounds checks */
759
757
            size_t const iters = MIN(oiters, iiters);
760
757
            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
757
            olimit = op[3] + symbols;
767
768
            /* Exit fast decoding loop once we reach the end. */
769
757
            if (op[3] == olimit)
770
114
                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
2.57k
            for (stream = 1; stream < 4; ++stream) {
777
1.92k
                if (ip[stream] < ip[stream - 1])
778
0
                    goto _out;
779
1.92k
            }
780
643
        }
781
782
643
#ifndef NDEBUG
783
2.57k
        for (stream = 1; stream < 4; ++stream) {
784
1.92k
            assert(ip[stream] >= ip[stream - 1]);
785
1.92k
        }
786
643
#endif
787
788
643
#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol)                 \
789
34.1k
    do {                                                        \
790
34.1k
        int const index = (int)(bits[(_stream)] >> 53);         \
791
34.1k
        int const entry = (int)dtable[index];                   \
792
34.1k
        bits[(_stream)] <<= (entry & 0x3F);                     \
793
34.1k
        op[(_stream)][(_symbol)] = (BYTE)((entry >> 8) & 0xFF); \
794
34.1k
    } while (0)
795
796
643
#define HUF_4X1_RELOAD_STREAM(_stream)                              \
797
6.83k
    do {                                                            \
798
6.83k
        int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
799
6.83k
        int const nbBits = ctz & 7;                                 \
800
6.83k
        int const nbBytes = ctz >> 3;                               \
801
6.83k
        op[(_stream)] += 5;                                         \
802
6.83k
        ip[(_stream)] -= nbBytes;                                   \
803
6.83k
        bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \
804
6.83k
        bits[(_stream)] <<= nbBits;                                 \
805
6.83k
    } while (0)
806
807
        /* Manually unroll the loop because compilers don't consistently
808
         * unroll the inner loops, which destroys performance.
809
         */
810
1.70k
        do {
811
            /* Decode 5 symbols in each of the 4 streams */
812
6.83k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 0);
813
6.83k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 1);
814
6.83k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 2);
815
6.83k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 3);
816
6.83k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4);
817
818
            /* Reload each of the 4 the bitstreams */
819
6.83k
            HUF_4X_FOR_EACH_STREAM(HUF_4X1_RELOAD_STREAM);
820
1.70k
        } while (op[3] < olimit);
821
822
643
#undef HUF_4X1_DECODE_SYMBOL
823
643
#undef HUF_4X1_RELOAD_STREAM
824
643
    }
825
826
114
_out:
827
828
    /* Save the final values of each of the state variables back to args. */
829
114
    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
830
114
    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));
831
114
    ZSTD_memcpy(&args->op, &op, sizeof(op));
832
114
}
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
321
{
847
321
    void const* dt = DTable + 1;
848
321
    BYTE const* const ilowest = (BYTE const*)cSrc;
849
321
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
850
321
    HUF_DecompressFastArgs args;
851
321
    {   size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
852
321
        FORWARD_IF_ERROR(ret, "Failed to init fast loop args");
853
285
        if (ret == 0)
854
171
            return 0;
855
285
    }
856
857
114
    assert(args.ip[0] >= args.ilowest);
858
114
    loopFn(&args);
859
860
    /* Our loop guarantees that ip[] >= ilowest and that we haven't
861
    * overwritten any op[].
862
    */
863
114
    assert(args.ip[0] >= ilowest);
864
114
    assert(args.ip[0] >= ilowest);
865
114
    assert(args.ip[1] >= ilowest);
866
114
    assert(args.ip[2] >= ilowest);
867
114
    assert(args.ip[3] >= ilowest);
868
114
    assert(args.op[3] <= oend);
869
870
114
    assert(ilowest == args.ilowest);
871
114
    assert(ilowest + 6 == args.iend[0]);
872
114
    (void)ilowest;
873
874
    /* finish bit streams one by one. */
875
114
    {   size_t const segmentSize = (dstSize+3) / 4;
876
114
        BYTE* segmentEnd = (BYTE*)dst;
877
114
        int i;
878
466
        for (i = 0; i < 4; ++i) {
879
398
            BIT_DStream_t bit;
880
398
            if (segmentSize <= (size_t)(oend - segmentEnd))
881
329
                segmentEnd += segmentSize;
882
69
            else
883
69
                segmentEnd = oend;
884
398
            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
885
            /* Decompress and validate that we've produced exactly the expected length. */
886
352
            args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG);
887
352
            if (args.op[i] != segmentEnd) return ERROR(corruption_detected);
888
352
        }
889
114
    }
890
891
    /* decoded size */
892
68
    assert(dstSize != 0);
893
68
    return dstSize;
894
114
}
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
321
{
901
321
    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default;
902
321
    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;
903
904
321
#if DYNAMIC_BMI2
905
321
    if (flags & HUF_flags_bmi2) {
906
321
        fallbackFn = HUF_decompress4X1_usingDTable_internal_bmi2;
907
# if ZSTD_ENABLE_ASM_X86_64_BMI2
908
        if (!(flags & HUF_flags_disableAsm)) {
909
            loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;
910
        }
911
# endif
912
321
    } else {
913
0
        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
914
0
    }
915
321
#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
321
    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {
924
321
        size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
925
321
        if (ret != 0)
926
150
            return ret;
927
321
    }
928
171
    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
929
321
}
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
459
{
935
459
    const BYTE* ip = (const BYTE*) cSrc;
936
937
459
    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);
938
459
    if (HUF_isError(hSize)) return hSize;
939
322
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
940
321
    ip += hSize; cSrcSize -= hSize;
941
942
321
    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
943
322
}
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
136k
{
964
136k
    U32 seq;
965
136k
    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0);
966
136k
    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2);
967
136k
    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3);
968
136k
    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32));
969
136k
    if (MEM_isLittleEndian()) {
970
136k
        seq = level == 1 ? symbol : (baseSeq + (symbol << 8));
971
136k
        return seq + (nbBits << 16) + ((U32)level << 24);
972
136k
    } else {
973
0
        seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol);
974
0
        return (seq << 16) + (nbBits << 8) + (U32)level;
975
0
    }
976
136k
}
977
978
/**
979
 * Constructs a HUF_DEltX2.
980
 */
981
static HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level)
982
80.7k
{
983
80.7k
    HUF_DEltX2 DElt;
984
80.7k
    U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
985
80.7k
    DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val));
986
80.7k
    ZSTD_memcpy(&DElt, &val, sizeof(val));
987
80.7k
    return DElt;
988
80.7k
}
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
56.1k
{
995
56.1k
    U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
996
56.1k
    return (U64)DElt + ((U64)DElt << 32);
997
56.1k
}
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
53.6k
{
1017
53.6k
    U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */);
1018
53.6k
    const sortedSymbol_t* ptr;
1019
53.6k
    assert(level >= 1 && level <= 2);
1020
53.6k
    switch (length) {
1021
12.8k
    case 1:
1022
55.4k
        for (ptr = begin; ptr != end; ++ptr) {
1023
42.5k
            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
1024
42.5k
            *DTableRank++ = DElt;
1025
42.5k
        }
1026
12.8k
        break;
1027
11.4k
    case 2:
1028
49.5k
        for (ptr = begin; ptr != end; ++ptr) {
1029
38.1k
            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
1030
38.1k
            DTableRank[0] = DElt;
1031
38.1k
            DTableRank[1] = DElt;
1032
38.1k
            DTableRank += 2;
1033
38.1k
        }
1034
11.4k
        break;
1035
9.84k
    case 4:
1036
23.5k
        for (ptr = begin; ptr != end; ++ptr) {
1037
13.6k
            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
1038
13.6k
            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
1039
13.6k
            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
1040
13.6k
            DTableRank += 4;
1041
13.6k
        }
1042
9.84k
        break;
1043
7.73k
    case 8:
1044
22.1k
        for (ptr = begin; ptr != end; ++ptr) {
1045
14.4k
            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
1046
14.4k
            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
1047
14.4k
            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
1048
14.4k
            ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
1049
14.4k
            ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
1050
14.4k
            DTableRank += 8;
1051
14.4k
        }
1052
7.73k
        break;
1053
11.7k
    default:
1054
27.7k
        for (ptr = begin; ptr != end; ++ptr) {
1055
15.9k
            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
1056
15.9k
            HUF_DEltX2* const DTableRankEnd = DTableRank + length;
1057
134k
            for (; DTableRank != DTableRankEnd; DTableRank += 8) {
1058
118k
                ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
1059
118k
                ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
1060
118k
                ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
1061
118k
                ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
1062
118k
            }
1063
15.9k
        }
1064
11.7k
        break;
1065
53.6k
    }
1066
53.6k
}
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
13.7k
{
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
13.7k
    if (minWeight>1) {
1080
12.0k
        U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */);
1081
12.0k
        U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1);
1082
12.0k
        int const skipSize = rankVal[minWeight];
1083
12.0k
        assert(length > 1);
1084
12.0k
        assert((U32)skipSize < length);
1085
12.0k
        switch (length) {
1086
692
        case 2:
1087
692
            assert(skipSize == 1);
1088
692
            ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2));
1089
692
            break;
1090
856
        case 4:
1091
856
            assert(skipSize <= 4);
1092
856
            ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2));
1093
856
            ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2));
1094
856
            break;
1095
10.5k
        default:
1096
10.5k
            {
1097
10.5k
                int i;
1098
25.9k
                for (i = 0; i < skipSize; i += 8) {
1099
15.3k
                    ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2));
1100
15.3k
                    ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2));
1101
15.3k
                    ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2));
1102
15.3k
                    ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2));
1103
15.3k
                }
1104
10.5k
            }
1105
12.0k
        }
1106
12.0k
    }
1107
1108
    /* Fill each of the second level symbols by weight. */
1109
13.7k
    {
1110
13.7k
        int w;
1111
67.1k
        for (w = minWeight; w < maxWeight1; ++w) {
1112
53.3k
            int const begin = rankStart[w];
1113
53.3k
            int const end = rankStart[w+1];
1114
53.3k
            U32 const nbBits = nbBitsBaseline - w;
1115
53.3k
            U32 const totalBits = nbBits + consumedBits;
1116
53.3k
            HUF_fillDTableX2ForWeight(
1117
53.3k
                DTable + rankVal[w],
1118
53.3k
                sortedSymbols + begin, sortedSymbols + end,
1119
53.3k
                totalBits, targetLog,
1120
53.3k
                baseSeq, /* level */ 2);
1121
53.3k
        }
1122
13.7k
    }
1123
13.7k
}
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
583
{
1130
583
    U32* const rankVal = rankValOrigin[0];
1131
583
    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */
1132
583
    const U32 minBits  = nbBitsBaseline - maxWeight;
1133
583
    int w;
1134
583
    int const wEnd = (int)maxWeight + 1;
1135
1136
    /* Fill DTable in order of weight. */
1137
5.09k
    for (w = 1; w < wEnd; ++w) {
1138
4.51k
        int const begin = (int)rankStart[w];
1139
4.51k
        int const end = (int)rankStart[w+1];
1140
4.51k
        U32 const nbBits = nbBitsBaseline - w;
1141
1142
4.51k
        if (targetLog-nbBits >= minBits) {
1143
            /* Enough room for a second symbol. */
1144
4.23k
            int start = rankVal[w];
1145
4.23k
            U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */);
1146
4.23k
            int minWeight = nbBits + scaleLog;
1147
4.23k
            int s;
1148
4.23k
            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
18.0k
            for (s = begin; s != end; ++s) {
1153
13.7k
                HUF_fillDTableX2Level2(
1154
13.7k
                    DTable + start, targetLog, nbBits,
1155
13.7k
                    rankValOrigin[nbBits], minWeight, wEnd,
1156
13.7k
                    sortedList, rankStart,
1157
13.7k
                    nbBitsBaseline, sortedList[s].symbol);
1158
13.7k
                start += length;
1159
13.7k
            }
1160
4.23k
        } else {
1161
            /* Only a single symbol. */
1162
271
            HUF_fillDTableX2ForWeight(
1163
271
                DTable + rankVal[w],
1164
271
                sortedList + begin, sortedList + end,
1165
271
                nbBits, targetLog,
1166
271
                /* baseSeq */ 0, /* level */ 1);
1167
271
        }
1168
4.51k
    }
1169
583
}
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
682
{
1184
682
    U32 tableLog, maxW, nbSymbols;
1185
682
    DTableDesc dtd = HUF_getDTableDesc(DTable);
1186
682
    U32 maxTableLog = dtd.maxTableLog;
1187
682
    size_t iSize;
1188
682
    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */
1189
682
    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
1190
682
    U32 *rankStart;
1191
1192
682
    HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;
1193
1194
682
    if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);
1195
1196
682
    rankStart = wksp->rankStart0 + 1;
1197
682
    ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));
1198
682
    ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));
1199
1200
682
    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */
1201
682
    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
682
    iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), flags);
1205
682
    if (HUF_isError(iSize)) return iSize;
1206
1207
    /* check result */
1208
583
    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */
1209
583
    if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG;
1210
1211
    /* find maxWeight */
1212
954
    for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */
1213
1214
    /* Get start index of each weight */
1215
583
    {   U32 w, nextRankStart = 0;
1216
5.09k
        for (w=1; w<maxW+1; w++) {
1217
4.51k
            U32 curr = nextRankStart;
1218
4.51k
            nextRankStart += wksp->rankStats[w];
1219
4.51k
            rankStart[w] = curr;
1220
4.51k
        }
1221
583
        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
1222
583
        rankStart[maxW+1] = nextRankStart;
1223
583
    }
1224
1225
    /* sort symbols by weight */
1226
583
    {   U32 s;
1227
54.0k
        for (s=0; s<nbSymbols; s++) {
1228
53.4k
            U32 const w = wksp->weightList[s];
1229
53.4k
            U32 const r = rankStart[w]++;
1230
53.4k
            wksp->sortedSymbol[r].symbol = (BYTE)s;
1231
53.4k
        }
1232
583
        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
1233
583
    }
1234
1235
    /* Build rankVal */
1236
583
    {   U32* const rankVal0 = wksp->rankVal[0];
1237
583
        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */
1238
583
            U32 nextRankVal = 0;
1239
583
            U32 w;
1240
5.09k
            for (w=1; w<maxW+1; w++) {
1241
4.51k
                U32 curr = nextRankVal;
1242
4.51k
                nextRankVal += wksp->rankStats[w] << (w+rescale);
1243
4.51k
                rankVal0[w] = curr;
1244
4.51k
        }   }
1245
583
        {   U32 const minBits = tableLog+1 - maxW;
1246
583
            U32 consumed;
1247
5.73k
            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
1248
5.15k
                U32* const rankValPtr = wksp->rankVal[consumed];
1249
5.15k
                U32 w;
1250
47.7k
                for (w = 1; w < maxW+1; w++) {
1251
42.6k
                    rankValPtr[w] = rankVal0[w] >> consumed;
1252
42.6k
    }   }   }   }
1253
1254
583
    HUF_fillDTableX2(dt, maxTableLog,
1255
583
                   wksp->sortedSymbol,
1256
583
                   wksp->rankStart0, wksp->rankVal, maxW,
1257
583
                   tableLog+1);
1258
1259
583
    dtd.tableLog = (BYTE)maxTableLog;
1260
583
    dtd.tableType = 1;
1261
583
    ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
1262
583
    return iSize;
1263
583
}
1264
1265
1266
FORCE_INLINE_TEMPLATE U32
1267
HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
1268
266k
{
1269
266k
    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
1270
266k
    ZSTD_memcpy(op, &dt[val].sequence, 2);
1271
266k
    BIT_skipBits(DStream, dt[val].nbBits);
1272
266k
    return dt[val].length;
1273
266k
}
1274
1275
FORCE_INLINE_TEMPLATE U32
1276
HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
1277
953
{
1278
953
    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
1279
953
    ZSTD_memcpy(op, &dt[val].sequence, 1);
1280
953
    if (dt[val].length==1) {
1281
346
        BIT_skipBits(DStream, dt[val].nbBits);
1282
607
    } else {
1283
607
        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
1284
208
            BIT_skipBits(DStream, dt[val].nbBits);
1285
208
            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
12
                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
1288
208
        }
1289
607
    }
1290
953
    return 1;
1291
953
}
1292
1293
#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
1294
255k
    do { ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); } while (0)
1295
1296
#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr)                     \
1297
3.64k
    do {                                                           \
1298
3.64k
        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12))                \
1299
3.64k
            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \
1300
3.64k
    } while (0)
1301
1302
#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr)                     \
1303
7.28k
    do {                                                           \
1304
7.28k
        if (MEM_64bits())                                          \
1305
7.28k
            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \
1306
7.28k
    } 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
1.51k
{
1312
1.51k
    BYTE* const pStart = p;
1313
1314
    /* up to 8 symbols at a time */
1315
1.51k
    if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) {
1316
1.47k
        if (dtLog <= 11 && MEM_64bits()) {
1317
            /* up to 10 symbols at a time */
1318
19.2k
            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) {
1319
17.9k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1320
17.9k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1321
17.9k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1322
17.9k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1323
17.9k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1324
17.9k
            }
1325
1.26k
        } else {
1326
            /* up to 8 symbols at a time */
1327
2.23k
            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
1328
2.02k
                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
1329
2.02k
                HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
1330
2.02k
                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
1331
2.02k
                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1332
2.02k
            }
1333
212
        }
1334
1.47k
    } else {
1335
34
        BIT_reloadDStream(bitDPtr);
1336
34
    }
1337
1338
    /* closer to end : up to 2 symbols at a time */
1339
1.51k
    if ((size_t)(pEnd - p) >= 2) {
1340
2.32k
        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
1341
882
            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
1342
1343
162k
        while (p <= pEnd-2)
1344
161k
            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
1345
1.44k
    }
1346
1347
1.51k
    if (p < pEnd)
1348
953
        p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
1349
1350
1.51k
    return p-pStart;
1351
1.51k
}
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
0
{
1359
0
    BIT_DStream_t bitD;
1360
1361
    /* Init */
1362
0
    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
1363
1364
    /* decode */
1365
0
    {   BYTE* const ostart = (BYTE*) dst;
1366
0
        BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)dstSize);
1367
0
        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */
1368
0
        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
1369
0
        DTableDesc const dtd = HUF_getDTableDesc(DTable);
1370
0
        HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);
1371
0
    }
1372
1373
    /* check */
1374
0
    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
1375
1376
    /* decoded size */
1377
0
    return dstSize;
1378
0
}
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
356
{
1390
356
    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
1391
356
    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */
1392
1393
356
    {   const BYTE* const istart = (const BYTE*) cSrc;
1394
356
        BYTE* const ostart = (BYTE*) dst;
1395
356
        BYTE* const oend = ostart + dstSize;
1396
356
        BYTE* const olimit = oend - (sizeof(size_t)-1);
1397
356
        const void* const dtPtr = DTable+1;
1398
356
        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
1399
1400
        /* Init */
1401
356
        BIT_DStream_t bitD1;
1402
356
        BIT_DStream_t bitD2;
1403
356
        BIT_DStream_t bitD3;
1404
356
        BIT_DStream_t bitD4;
1405
356
        size_t const length1 = MEM_readLE16(istart);
1406
356
        size_t const length2 = MEM_readLE16(istart+2);
1407
356
        size_t const length3 = MEM_readLE16(istart+4);
1408
356
        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
1409
356
        const BYTE* const istart1 = istart + 6;  /* jumpTable */
1410
356
        const BYTE* const istart2 = istart1 + length1;
1411
356
        const BYTE* const istart3 = istart2 + length2;
1412
356
        const BYTE* const istart4 = istart3 + length3;
1413
356
        size_t const segmentSize = (dstSize+3) / 4;
1414
356
        BYTE* const opStart2 = ostart + segmentSize;
1415
356
        BYTE* const opStart3 = opStart2 + segmentSize;
1416
356
        BYTE* const opStart4 = opStart3 + segmentSize;
1417
356
        BYTE* op1 = ostart;
1418
356
        BYTE* op2 = opStart2;
1419
356
        BYTE* op3 = opStart3;
1420
356
        BYTE* op4 = opStart4;
1421
356
        U32 endSignal = 1;
1422
356
        DTableDesc const dtd = HUF_getDTableDesc(DTable);
1423
356
        U32 const dtLog = dtd.tableLog;
1424
1425
356
        if (length4 > cSrcSize) return ERROR(corruption_detected);  /* overflow */
1426
324
        if (opStart4 > oend) return ERROR(corruption_detected);     /* overflow */
1427
324
        assert(dstSize >= 6 /* validated above */);
1428
324
        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
1429
303
        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
1430
291
        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
1431
280
        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
1432
1433
        /* 16-32 symbols per loop (4-8 symbols per stream) */
1434
274
        if ((size_t)(oend - op4) >= sizeof(size_t)) {
1435
680
            for ( ; (endSignal) & (op4 < olimit); ) {
1436
406
#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
1437
406
                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
1438
406
                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
1439
406
                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
1440
406
                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
1441
406
                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
1442
406
                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
1443
406
                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
1444
406
                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
1445
406
                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
1446
406
                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
1447
406
                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
1448
406
                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
1449
406
                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
1450
406
                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
1451
406
                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
1452
406
                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
1453
406
                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
1454
406
                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
1455
406
                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
1456
406
                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
406
            }
1481
274
        }
1482
1483
        /* check corruption */
1484
274
        if (op1 > opStart2) return ERROR(corruption_detected);
1485
274
        if (op2 > opStart3) return ERROR(corruption_detected);
1486
274
        if (op3 > opStart4) return ERROR(corruption_detected);
1487
        /* note : op4 already verified within main loop */
1488
1489
        /* finish bitStreams one by one */
1490
274
        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
1491
274
        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
1492
274
        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
1493
274
        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);
1494
1495
        /* check */
1496
274
        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
1497
274
          if (!endCheck) return ERROR(corruption_detected); }
1498
1499
        /* decoded size */
1500
0
        return dstSize;
1501
274
    }
1502
274
}
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
356
                    size_t cSrcSize, HUF_DTable const* DTable) {
1508
356
    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
1509
356
}
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
146
{
1527
146
    U64 bits[4];
1528
146
    BYTE const* ip[4];
1529
146
    BYTE* op[4];
1530
146
    BYTE* oend[4];
1531
146
    HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt;
1532
146
    BYTE const* const ilowest = args->ilowest;
1533
1534
    /* Copy the arguments to local registers. */
1535
146
    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
1536
146
    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));
1537
146
    ZSTD_memcpy(&op, &args->op, sizeof(op));
1538
1539
146
    oend[0] = op[1];
1540
146
    oend[1] = op[2];
1541
146
    oend[2] = op[3];
1542
146
    oend[3] = args->oend;
1543
1544
146
    assert(MEM_isLittleEndian());
1545
146
    assert(!MEM_32bits());
1546
1547
939
    for (;;) {
1548
939
        BYTE* olimit;
1549
939
        int stream;
1550
1551
        /* Assert loop preconditions */
1552
939
#ifndef NDEBUG
1553
4.69k
        for (stream = 0; stream < 4; ++stream) {
1554
3.75k
            assert(op[stream] <= oend[stream]);
1555
3.75k
            assert(ip[stream] >= ilowest);
1556
3.75k
        }
1557
939
#endif
1558
        /* Compute olimit */
1559
939
        {
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
939
            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
4.69k
            for (stream = 0; stream < 4; ++stream) {
1574
3.75k
                size_t const oiters = (size_t)(oend[stream] - op[stream]) / 10;
1575
3.75k
                iters = MIN(iters, oiters);
1576
3.75k
            }
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
939
            olimit = op[3] + (iters * 5);
1585
1586
            /* Exit the fast decoding loop once we reach the end. */
1587
939
            if (op[3] == olimit)
1588
146
                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
3.17k
            for (stream = 1; stream < 4; ++stream) {
1595
2.37k
                if (ip[stream] < ip[stream - 1])
1596
0
                    goto _out;
1597
2.37k
            }
1598
793
        }
1599
1600
793
#ifndef NDEBUG
1601
3.17k
        for (stream = 1; stream < 4; ++stream) {
1602
2.37k
            assert(ip[stream] >= ip[stream - 1]);
1603
2.37k
        }
1604
793
#endif
1605
1606
793
#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3)                      \
1607
67.5k
    do {                                                              \
1608
67.5k
        if ((_decode3) || (_stream) != 3) {                           \
1609
54.0k
            int const index = (int)(bits[(_stream)] >> 53);           \
1610
54.0k
            HUF_DEltX2 const entry = dtable[index];                   \
1611
54.0k
            MEM_write16(op[(_stream)], entry.sequence); \
1612
54.0k
            bits[(_stream)] <<= (entry.nbBits) & 0x3F;                \
1613
54.0k
            op[(_stream)] += (entry.length);                          \
1614
54.0k
        }                                                             \
1615
67.5k
    } while (0)
1616
1617
793
#define HUF_4X2_RELOAD_STREAM(_stream)                                  \
1618
10.8k
    do {                                                                \
1619
10.8k
        HUF_4X2_DECODE_SYMBOL(3, 1);                                    \
1620
10.8k
        {                                                               \
1621
10.8k
            int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \
1622
10.8k
            int const nbBits = ctz & 7;                                 \
1623
10.8k
            int const nbBytes = ctz >> 3;                               \
1624
10.8k
            ip[(_stream)] -= nbBytes;                                   \
1625
10.8k
            bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \
1626
10.8k
            bits[(_stream)] <<= nbBits;                                 \
1627
10.8k
        }                                                               \
1628
10.8k
    } while (0)
1629
1630
        /* Manually unroll the loop because compilers don't consistently
1631
         * unroll the inner loops, which destroys performance.
1632
         */
1633
2.70k
        do {
1634
            /* Decode 5 symbols from each of the first 3 streams.
1635
             * The final stream will be decoded during the reload phase
1636
             * to reduce register pressure.
1637
             */
1638
10.8k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
1639
10.8k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
1640
10.8k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
1641
10.8k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
1642
10.8k
            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);
1643
1644
            /* Decode one symbol from the final stream */
1645
2.70k
            HUF_4X2_DECODE_SYMBOL(3, 1);
1646
1647
            /* Decode 4 symbols from the final stream & reload bitstreams.
1648
             * The final stream is reloaded last, meaning that all 5 symbols
1649
             * are decoded from the final stream before it is reloaded.
1650
             */
1651
10.8k
            HUF_4X_FOR_EACH_STREAM(HUF_4X2_RELOAD_STREAM);
1652
2.70k
        } while (op[3] < olimit);
1653
793
    }
1654
1655
146
#undef HUF_4X2_DECODE_SYMBOL
1656
146
#undef HUF_4X2_RELOAD_STREAM
1657
1658
146
_out:
1659
1660
    /* Save the final values of each of the state variables back to args. */
1661
146
    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
1662
146
    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));
1663
146
    ZSTD_memcpy(&args->op, &op, sizeof(op));
1664
146
}
1665
1666
1667
static HUF_FAST_BMI2_ATTRS size_t
1668
HUF_decompress4X2_usingDTable_internal_fast(
1669
          void* dst,  size_t dstSize,
1670
    const void* cSrc, size_t cSrcSize,
1671
    const HUF_DTable* DTable,
1672
583
    HUF_DecompressFastLoopFn loopFn) {
1673
583
    void const* dt = DTable + 1;
1674
583
    const BYTE* const ilowest = (const BYTE*)cSrc;
1675
583
    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);
1676
583
    HUF_DecompressFastArgs args;
1677
583
    {
1678
583
        size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
1679
583
        FORWARD_IF_ERROR(ret, "Failed to init asm args");
1680
502
        if (ret == 0)
1681
356
            return 0;
1682
502
    }
1683
1684
146
    assert(args.ip[0] >= args.ilowest);
1685
146
    loopFn(&args);
1686
1687
    /* note : op4 already verified within main loop */
1688
146
    assert(args.ip[0] >= ilowest);
1689
146
    assert(args.ip[1] >= ilowest);
1690
146
    assert(args.ip[2] >= ilowest);
1691
146
    assert(args.ip[3] >= ilowest);
1692
146
    assert(args.op[3] <= oend);
1693
1694
146
    assert(ilowest == args.ilowest);
1695
146
    assert(ilowest + 6 == args.iend[0]);
1696
146
    (void)ilowest;
1697
1698
    /* finish bitStreams one by one */
1699
146
    {
1700
146
        size_t const segmentSize = (dstSize+3) / 4;
1701
146
        BYTE* segmentEnd = (BYTE*)dst;
1702
146
        int i;
1703
560
        for (i = 0; i < 4; ++i) {
1704
485
            BIT_DStream_t bit;
1705
485
            if (segmentSize <= (size_t)(oend - segmentEnd))
1706
408
                segmentEnd += segmentSize;
1707
77
            else
1708
77
                segmentEnd = oend;
1709
485
            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
1710
414
            args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG);
1711
414
            if (args.op[i] != segmentEnd)
1712
0
                return ERROR(corruption_detected);
1713
414
        }
1714
146
    }
1715
1716
    /* decoded size */
1717
75
    return dstSize;
1718
146
}
1719
1720
static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
1721
                    size_t cSrcSize, HUF_DTable const* DTable, int flags)
1722
583
{
1723
583
    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default;
1724
583
    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;
1725
1726
583
#if DYNAMIC_BMI2
1727
583
    if (flags & HUF_flags_bmi2) {
1728
583
        fallbackFn = HUF_decompress4X2_usingDTable_internal_bmi2;
1729
# if ZSTD_ENABLE_ASM_X86_64_BMI2
1730
        if (!(flags & HUF_flags_disableAsm)) {
1731
            loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;
1732
        }
1733
# endif
1734
583
    } else {
1735
0
        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
1736
0
    }
1737
583
#endif
1738
1739
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
1740
    if (!(flags & HUF_flags_disableAsm)) {
1741
        loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;
1742
    }
1743
#endif
1744
1745
583
    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {
1746
583
        size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
1747
583
        if (ret != 0)
1748
227
            return ret;
1749
583
    }
1750
356
    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
1751
583
}
1752
1753
HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
1754
1755
size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
1756
                                   const void* cSrc, size_t cSrcSize,
1757
                                   void* workSpace, size_t wkspSize, int flags)
1758
0
{
1759
0
    const BYTE* ip = (const BYTE*) cSrc;
1760
1761
0
    size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
1762
0
                                               workSpace, wkspSize, flags);
1763
0
    if (HUF_isError(hSize)) return hSize;
1764
0
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1765
0
    ip += hSize; cSrcSize -= hSize;
1766
1767
0
    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, flags);
1768
0
}
1769
1770
static size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
1771
                                   const void* cSrc, size_t cSrcSize,
1772
                                   void* workSpace, size_t wkspSize, int flags)
1773
682
{
1774
682
    const BYTE* ip = (const BYTE*) cSrc;
1775
1776
682
    size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
1777
682
                                         workSpace, wkspSize, flags);
1778
682
    if (HUF_isError(hSize)) return hSize;
1779
583
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1780
583
    ip += hSize; cSrcSize -= hSize;
1781
1782
583
    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
1783
583
}
1784
1785
#endif /* HUF_FORCE_DECOMPRESS_X1 */
1786
1787
1788
/* ***********************************/
1789
/* Universal decompression selectors */
1790
/* ***********************************/
1791
1792
1793
#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
1794
typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
1795
static const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] =
1796
{
1797
    /* single, double, quad */
1798
    {{0,0}, {1,1}},  /* Q==0 : impossible */
1799
    {{0,0}, {1,1}},  /* Q==1 : impossible */
1800
    {{ 150,216}, { 381,119}},   /* Q == 2 : 12-18% */
1801
    {{ 170,205}, { 514,112}},   /* Q == 3 : 18-25% */
1802
    {{ 177,199}, { 539,110}},   /* Q == 4 : 25-32% */
1803
    {{ 197,194}, { 644,107}},   /* Q == 5 : 32-38% */
1804
    {{ 221,192}, { 735,107}},   /* Q == 6 : 38-44% */
1805
    {{ 256,189}, { 881,106}},   /* Q == 7 : 44-50% */
1806
    {{ 359,188}, {1167,109}},   /* Q == 8 : 50-56% */
1807
    {{ 582,187}, {1570,114}},   /* Q == 9 : 56-62% */
1808
    {{ 688,187}, {1712,122}},   /* Q ==10 : 62-69% */
1809
    {{ 825,186}, {1965,136}},   /* Q ==11 : 69-75% */
1810
    {{ 976,185}, {2131,150}},   /* Q ==12 : 75-81% */
1811
    {{1180,186}, {2070,175}},   /* Q ==13 : 81-87% */
1812
    {{1377,185}, {1731,202}},   /* Q ==14 : 87-93% */
1813
    {{1412,185}, {1695,202}},   /* Q ==15 : 93-99% */
1814
};
1815
#endif
1816
1817
/** HUF_selectDecoder() :
1818
 *  Tells which decoder is likely to decode faster,
1819
 *  based on a set of pre-computed metrics.
1820
 * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
1821
 *  Assumption : 0 < dstSize <= 128 KB */
1822
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
1823
1.14k
{
1824
1.14k
    assert(dstSize > 0);
1825
1.14k
    assert(dstSize <= 128*1024);
1826
#if defined(HUF_FORCE_DECOMPRESS_X1)
1827
    (void)dstSize;
1828
    (void)cSrcSize;
1829
    return 0;
1830
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1831
    (void)dstSize;
1832
    (void)cSrcSize;
1833
    return 1;
1834
#else
1835
    /* decoder timing evaluation */
1836
1.14k
    {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */
1837
1.14k
        U32 const D256 = (U32)(dstSize >> 8);
1838
1.14k
        U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
1839
1.14k
        U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
1840
1.14k
        DTime1 += DTime1 >> 5;  /* small advantage to algorithm using less memory, to reduce cache eviction */
1841
1.14k
        return DTime1 < DTime0;
1842
1.14k
    }
1843
1.14k
#endif
1844
1.14k
}
1845
1846
size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
1847
                                  const void* cSrc, size_t cSrcSize,
1848
                                  void* workSpace, size_t wkspSize, int flags)
1849
0
{
1850
    /* validation checks */
1851
0
    if (dstSize == 0) return ERROR(dstSize_tooSmall);
1852
0
    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
1853
0
    if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
1854
0
    if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
1855
1856
0
    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1857
#if defined(HUF_FORCE_DECOMPRESS_X1)
1858
        (void)algoNb;
1859
        assert(algoNb == 0);
1860
        return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
1861
                                cSrcSize, workSpace, wkspSize, flags);
1862
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1863
        (void)algoNb;
1864
        assert(algoNb == 1);
1865
        return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
1866
                                cSrcSize, workSpace, wkspSize, flags);
1867
#else
1868
0
        return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
1869
0
                                cSrcSize, workSpace, wkspSize, flags):
1870
0
                        HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
1871
0
                                cSrcSize, workSpace, wkspSize, flags);
1872
0
#endif
1873
0
    }
1874
0
}
1875
1876
1877
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)
1878
0
{
1879
0
    DTableDesc const dtd = HUF_getDTableDesc(DTable);
1880
#if defined(HUF_FORCE_DECOMPRESS_X1)
1881
    (void)dtd;
1882
    assert(dtd.tableType == 0);
1883
    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1884
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1885
    (void)dtd;
1886
    assert(dtd.tableType == 1);
1887
    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1888
#else
1889
0
    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :
1890
0
                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1891
0
#endif
1892
0
}
1893
1894
#ifndef HUF_FORCE_DECOMPRESS_X2
1895
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)
1896
98
{
1897
98
    const BYTE* ip = (const BYTE*) cSrc;
1898
1899
98
    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);
1900
98
    if (HUF_isError(hSize)) return hSize;
1901
61
    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
1902
60
    ip += hSize; cSrcSize -= hSize;
1903
1904
60
    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
1905
61
}
1906
#endif
1907
1908
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)
1909
0
{
1910
0
    DTableDesc const dtd = HUF_getDTableDesc(DTable);
1911
#if defined(HUF_FORCE_DECOMPRESS_X1)
1912
    (void)dtd;
1913
    assert(dtd.tableType == 0);
1914
    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1915
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1916
    (void)dtd;
1917
    assert(dtd.tableType == 1);
1918
    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1919
#else
1920
0
    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :
1921
0
                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
1922
0
#endif
1923
0
}
1924
1925
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)
1926
1.14k
{
1927
    /* validation checks */
1928
1.14k
    if (dstSize == 0) return ERROR(dstSize_tooSmall);
1929
1.14k
    if (cSrcSize == 0) return ERROR(corruption_detected);
1930
1931
1.14k
    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
1932
#if defined(HUF_FORCE_DECOMPRESS_X1)
1933
        (void)algoNb;
1934
        assert(algoNb == 0);
1935
        return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
1936
#elif defined(HUF_FORCE_DECOMPRESS_X2)
1937
        (void)algoNb;
1938
        assert(algoNb == 1);
1939
        return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
1940
#else
1941
1.14k
        return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags) :
1942
1.14k
                        HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
1943
1.14k
#endif
1944
1.14k
    }
1945
1.14k
}