cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zstd_compress.c (219897B)


      1/*
      2 * Copyright (c) Yann Collet, Facebook, Inc.
      3 * All rights reserved.
      4 *
      5 * This source code is licensed under both the BSD-style license (found in the
      6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
      7 * in the COPYING file in the root directory of this source tree).
      8 * You may select, at your option, one of the above-listed licenses.
      9 */
     10
     11/*-*************************************
     12*  Dependencies
     13***************************************/
     14#include "../common/zstd_deps.h"  /* INT_MAX, ZSTD_memset, ZSTD_memcpy */
     15#include "../common/cpu.h"
     16#include "../common/mem.h"
     17#include "hist.h"           /* HIST_countFast_wksp */
     18#define FSE_STATIC_LINKING_ONLY   /* FSE_encodeSymbol */
     19#include "../common/fse.h"
     20#define HUF_STATIC_LINKING_ONLY
     21#include "../common/huf.h"
     22#include "zstd_compress_internal.h"
     23#include "zstd_compress_sequences.h"
     24#include "zstd_compress_literals.h"
     25#include "zstd_fast.h"
     26#include "zstd_double_fast.h"
     27#include "zstd_lazy.h"
     28#include "zstd_opt.h"
     29#include "zstd_ldm.h"
     30#include "zstd_compress_superblock.h"
     31
     32/* ***************************************************************
     33*  Tuning parameters
     34*****************************************************************/
     35/*!
     36 * COMPRESS_HEAPMODE :
     37 * Select how default decompression function ZSTD_compress() allocates its context,
     38 * on stack (0, default), or into heap (1).
     39 * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected.
     40 */
     41
     42
     43/*-*************************************
     44*  Helper functions
     45***************************************/
     46/* ZSTD_compressBound()
     47 * Note that the result from this function is only compatible with the "normal"
     48 * full-block strategy.
     49 * When there are a lot of small blocks due to frequent flush in streaming mode
     50 * the overhead of headers can make the compressed data to be larger than the
     51 * return value of ZSTD_compressBound().
     52 */
     53size_t ZSTD_compressBound(size_t srcSize) {
     54    return ZSTD_COMPRESSBOUND(srcSize);
     55}
     56
     57
     58/*-*************************************
     59*  Context memory management
     60***************************************/
     61struct ZSTD_CDict_s {
     62    const void* dictContent;
     63    size_t dictContentSize;
     64    ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */
     65    U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
     66    ZSTD_cwksp workspace;
     67    ZSTD_matchState_t matchState;
     68    ZSTD_compressedBlockState_t cBlockState;
     69    ZSTD_customMem customMem;
     70    U32 dictID;
     71    int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
     72};  /* typedef'd to ZSTD_CDict within "zstd.h" */
     73
     74ZSTD_CCtx* ZSTD_createCCtx(void)
     75{
     76    return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
     77}
     78
     79static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
     80{
     81    assert(cctx != NULL);
     82    ZSTD_memset(cctx, 0, sizeof(*cctx));
     83    cctx->customMem = memManager;
     84    cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
     85    {   size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
     86        assert(!ZSTD_isError(err));
     87        (void)err;
     88    }
     89}
     90
     91ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
     92{
     93    ZSTD_STATIC_ASSERT(zcss_init==0);
     94    ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
     95    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
     96    {   ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem);
     97        if (!cctx) return NULL;
     98        ZSTD_initCCtx(cctx, customMem);
     99        return cctx;
    100    }
    101}
    102
    103ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
    104{
    105    ZSTD_cwksp ws;
    106    ZSTD_CCtx* cctx;
    107    if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL;  /* minimum size */
    108    if ((size_t)workspace & 7) return NULL;  /* must be 8-aligned */
    109    ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
    110
    111    cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));
    112    if (cctx == NULL) return NULL;
    113
    114    ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx));
    115    ZSTD_cwksp_move(&cctx->workspace, &ws);
    116    cctx->staticSize = workspaceSize;
    117
    118    /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
    119    if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
    120    cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
    121    cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
    122    cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE);
    123    cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
    124    return cctx;
    125}
    126
    127/*
    128 * Clears and frees all of the dictionaries in the CCtx.
    129 */
    130static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
    131{
    132    ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem);
    133    ZSTD_freeCDict(cctx->localDict.cdict);
    134    ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict));
    135    ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
    136    cctx->cdict = NULL;
    137}
    138
    139static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
    140{
    141    size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
    142    size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
    143    return bufferSize + cdictSize;
    144}
    145
    146static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
    147{
    148    assert(cctx != NULL);
    149    assert(cctx->staticSize == 0);
    150    ZSTD_clearAllDicts(cctx);
    151    ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);
    152}
    153
    154size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
    155{
    156    if (cctx==NULL) return 0;   /* support free on NULL */
    157    RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
    158                    "not compatible with static CCtx");
    159    {
    160        int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);
    161        ZSTD_freeCCtxContent(cctx);
    162        if (!cctxInWorkspace) {
    163            ZSTD_customFree(cctx, cctx->customMem);
    164        }
    165    }
    166    return 0;
    167}
    168
    169
    170static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
    171{
    172    (void)cctx;
    173    return 0;
    174}
    175
    176
    177size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
    178{
    179    if (cctx==NULL) return 0;   /* support sizeof on NULL */
    180    /* cctx may be in the workspace */
    181    return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))
    182           + ZSTD_cwksp_sizeof(&cctx->workspace)
    183           + ZSTD_sizeof_localDict(cctx->localDict)
    184           + ZSTD_sizeof_mtctx(cctx);
    185}
    186
    187size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
    188{
    189    return ZSTD_sizeof_CCtx(zcs);  /* same object */
    190}
    191
    192/* private API call, for dictBuilder only */
    193const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
    194
    195/* Returns 1 if compression parameters are such that we should
    196 * enable long distance matching (wlog >= 27, strategy >= btopt).
    197 * Returns 0 otherwise.
    198 */
    199static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) {
    200    return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27;
    201}
    202
    203static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
    204        ZSTD_compressionParameters cParams)
    205{
    206    ZSTD_CCtx_params cctxParams;
    207    /* should not matter, as all cParams are presumed properly defined */
    208    ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT);
    209    cctxParams.cParams = cParams;
    210
    211    if (ZSTD_CParams_shouldEnableLdm(&cParams)) {
    212        DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params");
    213        cctxParams.ldmParams.enableLdm = 1;
    214        /* LDM is enabled by default for optimal parser and window size >= 128MB */
    215        ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);
    216        assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);
    217        assert(cctxParams.ldmParams.hashRateLog < 32);
    218    }
    219
    220    assert(!ZSTD_checkCParams(cParams));
    221    return cctxParams;
    222}
    223
    224static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
    225        ZSTD_customMem customMem)
    226{
    227    ZSTD_CCtx_params* params;
    228    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
    229    params = (ZSTD_CCtx_params*)ZSTD_customCalloc(
    230            sizeof(ZSTD_CCtx_params), customMem);
    231    if (!params) { return NULL; }
    232    ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
    233    params->customMem = customMem;
    234    return params;
    235}
    236
    237ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
    238{
    239    return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);
    240}
    241
    242size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
    243{
    244    if (params == NULL) { return 0; }
    245    ZSTD_customFree(params, params->customMem);
    246    return 0;
    247}
    248
    249size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
    250{
    251    return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
    252}
    253
    254size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
    255    RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
    256    ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
    257    cctxParams->compressionLevel = compressionLevel;
    258    cctxParams->fParams.contentSizeFlag = 1;
    259    return 0;
    260}
    261
    262#define ZSTD_NO_CLEVEL 0
    263
    264/*
    265 * Initializes the cctxParams from params and compressionLevel.
    266 * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL.
    267 */
    268static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_parameters const* params, int compressionLevel)
    269{
    270    assert(!ZSTD_checkCParams(params->cParams));
    271    ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
    272    cctxParams->cParams = params->cParams;
    273    cctxParams->fParams = params->fParams;
    274    /* Should not matter, as all cParams are presumed properly defined.
    275     * But, set it for tracing anyway.
    276     */
    277    cctxParams->compressionLevel = compressionLevel;
    278}
    279
    280size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
    281{
    282    RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
    283    FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
    284    ZSTD_CCtxParams_init_internal(cctxParams, &params, ZSTD_NO_CLEVEL);
    285    return 0;
    286}
    287
    288/*
    289 * Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone.
    290 * @param param Validated zstd parameters.
    291 */
    292static void ZSTD_CCtxParams_setZstdParams(
    293        ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
    294{
    295    assert(!ZSTD_checkCParams(params->cParams));
    296    cctxParams->cParams = params->cParams;
    297    cctxParams->fParams = params->fParams;
    298    /* Should not matter, as all cParams are presumed properly defined.
    299     * But, set it for tracing anyway.
    300     */
    301    cctxParams->compressionLevel = ZSTD_NO_CLEVEL;
    302}
    303
    304ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
    305{
    306    ZSTD_bounds bounds = { 0, 0, 0 };
    307
    308    switch(param)
    309    {
    310    case ZSTD_c_compressionLevel:
    311        bounds.lowerBound = ZSTD_minCLevel();
    312        bounds.upperBound = ZSTD_maxCLevel();
    313        return bounds;
    314
    315    case ZSTD_c_windowLog:
    316        bounds.lowerBound = ZSTD_WINDOWLOG_MIN;
    317        bounds.upperBound = ZSTD_WINDOWLOG_MAX;
    318        return bounds;
    319
    320    case ZSTD_c_hashLog:
    321        bounds.lowerBound = ZSTD_HASHLOG_MIN;
    322        bounds.upperBound = ZSTD_HASHLOG_MAX;
    323        return bounds;
    324
    325    case ZSTD_c_chainLog:
    326        bounds.lowerBound = ZSTD_CHAINLOG_MIN;
    327        bounds.upperBound = ZSTD_CHAINLOG_MAX;
    328        return bounds;
    329
    330    case ZSTD_c_searchLog:
    331        bounds.lowerBound = ZSTD_SEARCHLOG_MIN;
    332        bounds.upperBound = ZSTD_SEARCHLOG_MAX;
    333        return bounds;
    334
    335    case ZSTD_c_minMatch:
    336        bounds.lowerBound = ZSTD_MINMATCH_MIN;
    337        bounds.upperBound = ZSTD_MINMATCH_MAX;
    338        return bounds;
    339
    340    case ZSTD_c_targetLength:
    341        bounds.lowerBound = ZSTD_TARGETLENGTH_MIN;
    342        bounds.upperBound = ZSTD_TARGETLENGTH_MAX;
    343        return bounds;
    344
    345    case ZSTD_c_strategy:
    346        bounds.lowerBound = ZSTD_STRATEGY_MIN;
    347        bounds.upperBound = ZSTD_STRATEGY_MAX;
    348        return bounds;
    349
    350    case ZSTD_c_contentSizeFlag:
    351        bounds.lowerBound = 0;
    352        bounds.upperBound = 1;
    353        return bounds;
    354
    355    case ZSTD_c_checksumFlag:
    356        bounds.lowerBound = 0;
    357        bounds.upperBound = 1;
    358        return bounds;
    359
    360    case ZSTD_c_dictIDFlag:
    361        bounds.lowerBound = 0;
    362        bounds.upperBound = 1;
    363        return bounds;
    364
    365    case ZSTD_c_nbWorkers:
    366        bounds.lowerBound = 0;
    367        bounds.upperBound = 0;
    368        return bounds;
    369
    370    case ZSTD_c_jobSize:
    371        bounds.lowerBound = 0;
    372        bounds.upperBound = 0;
    373        return bounds;
    374
    375    case ZSTD_c_overlapLog:
    376        bounds.lowerBound = 0;
    377        bounds.upperBound = 0;
    378        return bounds;
    379
    380    case ZSTD_c_enableDedicatedDictSearch:
    381        bounds.lowerBound = 0;
    382        bounds.upperBound = 1;
    383        return bounds;
    384
    385    case ZSTD_c_enableLongDistanceMatching:
    386        bounds.lowerBound = 0;
    387        bounds.upperBound = 1;
    388        return bounds;
    389
    390    case ZSTD_c_ldmHashLog:
    391        bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN;
    392        bounds.upperBound = ZSTD_LDM_HASHLOG_MAX;
    393        return bounds;
    394
    395    case ZSTD_c_ldmMinMatch:
    396        bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN;
    397        bounds.upperBound = ZSTD_LDM_MINMATCH_MAX;
    398        return bounds;
    399
    400    case ZSTD_c_ldmBucketSizeLog:
    401        bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;
    402        bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;
    403        return bounds;
    404
    405    case ZSTD_c_ldmHashRateLog:
    406        bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN;
    407        bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX;
    408        return bounds;
    409
    410    /* experimental parameters */
    411    case ZSTD_c_rsyncable:
    412        bounds.lowerBound = 0;
    413        bounds.upperBound = 1;
    414        return bounds;
    415
    416    case ZSTD_c_forceMaxWindow :
    417        bounds.lowerBound = 0;
    418        bounds.upperBound = 1;
    419        return bounds;
    420
    421    case ZSTD_c_format:
    422        ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
    423        bounds.lowerBound = ZSTD_f_zstd1;
    424        bounds.upperBound = ZSTD_f_zstd1_magicless;   /* note : how to ensure at compile time that this is the highest value enum ? */
    425        return bounds;
    426
    427    case ZSTD_c_forceAttachDict:
    428        ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);
    429        bounds.lowerBound = ZSTD_dictDefaultAttach;
    430        bounds.upperBound = ZSTD_dictForceLoad;       /* note : how to ensure at compile time that this is the highest value enum ? */
    431        return bounds;
    432
    433    case ZSTD_c_literalCompressionMode:
    434        ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
    435        bounds.lowerBound = ZSTD_lcm_auto;
    436        bounds.upperBound = ZSTD_lcm_uncompressed;
    437        return bounds;
    438
    439    case ZSTD_c_targetCBlockSize:
    440        bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
    441        bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
    442        return bounds;
    443
    444    case ZSTD_c_srcSizeHint:
    445        bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;
    446        bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
    447        return bounds;
    448
    449    case ZSTD_c_stableInBuffer:
    450    case ZSTD_c_stableOutBuffer:
    451        bounds.lowerBound = (int)ZSTD_bm_buffered;
    452        bounds.upperBound = (int)ZSTD_bm_stable;
    453        return bounds;
    454
    455    case ZSTD_c_blockDelimiters:
    456        bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;
    457        bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;
    458        return bounds;
    459
    460    case ZSTD_c_validateSequences:
    461        bounds.lowerBound = 0;
    462        bounds.upperBound = 1;
    463        return bounds;
    464
    465    default:
    466        bounds.error = ERROR(parameter_unsupported);
    467        return bounds;
    468    }
    469}
    470
    471/* ZSTD_cParam_clampBounds:
    472 * Clamps the value into the bounded range.
    473 */
    474static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
    475{
    476    ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
    477    if (ZSTD_isError(bounds.error)) return bounds.error;
    478    if (*value < bounds.lowerBound) *value = bounds.lowerBound;
    479    if (*value > bounds.upperBound) *value = bounds.upperBound;
    480    return 0;
    481}
    482
    483#define BOUNDCHECK(cParam, val) { \
    484    RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
    485                    parameter_outOfBound, "Param out of bounds"); \
    486}
    487
    488
    489static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
    490{
    491    switch(param)
    492    {
    493    case ZSTD_c_compressionLevel:
    494    case ZSTD_c_hashLog:
    495    case ZSTD_c_chainLog:
    496    case ZSTD_c_searchLog:
    497    case ZSTD_c_minMatch:
    498    case ZSTD_c_targetLength:
    499    case ZSTD_c_strategy:
    500        return 1;
    501
    502    case ZSTD_c_format:
    503    case ZSTD_c_windowLog:
    504    case ZSTD_c_contentSizeFlag:
    505    case ZSTD_c_checksumFlag:
    506    case ZSTD_c_dictIDFlag:
    507    case ZSTD_c_forceMaxWindow :
    508    case ZSTD_c_nbWorkers:
    509    case ZSTD_c_jobSize:
    510    case ZSTD_c_overlapLog:
    511    case ZSTD_c_rsyncable:
    512    case ZSTD_c_enableDedicatedDictSearch:
    513    case ZSTD_c_enableLongDistanceMatching:
    514    case ZSTD_c_ldmHashLog:
    515    case ZSTD_c_ldmMinMatch:
    516    case ZSTD_c_ldmBucketSizeLog:
    517    case ZSTD_c_ldmHashRateLog:
    518    case ZSTD_c_forceAttachDict:
    519    case ZSTD_c_literalCompressionMode:
    520    case ZSTD_c_targetCBlockSize:
    521    case ZSTD_c_srcSizeHint:
    522    case ZSTD_c_stableInBuffer:
    523    case ZSTD_c_stableOutBuffer:
    524    case ZSTD_c_blockDelimiters:
    525    case ZSTD_c_validateSequences:
    526    default:
    527        return 0;
    528    }
    529}
    530
    531size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
    532{
    533    DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value);
    534    if (cctx->streamStage != zcss_init) {
    535        if (ZSTD_isUpdateAuthorized(param)) {
    536            cctx->cParamsChanged = 1;
    537        } else {
    538            RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
    539    }   }
    540
    541    switch(param)
    542    {
    543    case ZSTD_c_nbWorkers:
    544        RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
    545                        "MT not compatible with static alloc");
    546        break;
    547
    548    case ZSTD_c_compressionLevel:
    549    case ZSTD_c_windowLog:
    550    case ZSTD_c_hashLog:
    551    case ZSTD_c_chainLog:
    552    case ZSTD_c_searchLog:
    553    case ZSTD_c_minMatch:
    554    case ZSTD_c_targetLength:
    555    case ZSTD_c_strategy:
    556    case ZSTD_c_ldmHashRateLog:
    557    case ZSTD_c_format:
    558    case ZSTD_c_contentSizeFlag:
    559    case ZSTD_c_checksumFlag:
    560    case ZSTD_c_dictIDFlag:
    561    case ZSTD_c_forceMaxWindow:
    562    case ZSTD_c_forceAttachDict:
    563    case ZSTD_c_literalCompressionMode:
    564    case ZSTD_c_jobSize:
    565    case ZSTD_c_overlapLog:
    566    case ZSTD_c_rsyncable:
    567    case ZSTD_c_enableDedicatedDictSearch:
    568    case ZSTD_c_enableLongDistanceMatching:
    569    case ZSTD_c_ldmHashLog:
    570    case ZSTD_c_ldmMinMatch:
    571    case ZSTD_c_ldmBucketSizeLog:
    572    case ZSTD_c_targetCBlockSize:
    573    case ZSTD_c_srcSizeHint:
    574    case ZSTD_c_stableInBuffer:
    575    case ZSTD_c_stableOutBuffer:
    576    case ZSTD_c_blockDelimiters:
    577    case ZSTD_c_validateSequences:
    578        break;
    579
    580    default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
    581    }
    582    return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
    583}
    584
    585size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
    586                                    ZSTD_cParameter param, int value)
    587{
    588    DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
    589    switch(param)
    590    {
    591    case ZSTD_c_format :
    592        BOUNDCHECK(ZSTD_c_format, value);
    593        CCtxParams->format = (ZSTD_format_e)value;
    594        return (size_t)CCtxParams->format;
    595
    596    case ZSTD_c_compressionLevel : {
    597        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
    598        if (value == 0)
    599            CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
    600        else
    601            CCtxParams->compressionLevel = value;
    602        if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
    603        return 0;  /* return type (size_t) cannot represent negative values */
    604    }
    605
    606    case ZSTD_c_windowLog :
    607        if (value!=0)   /* 0 => use default */
    608            BOUNDCHECK(ZSTD_c_windowLog, value);
    609        CCtxParams->cParams.windowLog = (U32)value;
    610        return CCtxParams->cParams.windowLog;
    611
    612    case ZSTD_c_hashLog :
    613        if (value!=0)   /* 0 => use default */
    614            BOUNDCHECK(ZSTD_c_hashLog, value);
    615        CCtxParams->cParams.hashLog = (U32)value;
    616        return CCtxParams->cParams.hashLog;
    617
    618    case ZSTD_c_chainLog :
    619        if (value!=0)   /* 0 => use default */
    620            BOUNDCHECK(ZSTD_c_chainLog, value);
    621        CCtxParams->cParams.chainLog = (U32)value;
    622        return CCtxParams->cParams.chainLog;
    623
    624    case ZSTD_c_searchLog :
    625        if (value!=0)   /* 0 => use default */
    626            BOUNDCHECK(ZSTD_c_searchLog, value);
    627        CCtxParams->cParams.searchLog = (U32)value;
    628        return (size_t)value;
    629
    630    case ZSTD_c_minMatch :
    631        if (value!=0)   /* 0 => use default */
    632            BOUNDCHECK(ZSTD_c_minMatch, value);
    633        CCtxParams->cParams.minMatch = value;
    634        return CCtxParams->cParams.minMatch;
    635
    636    case ZSTD_c_targetLength :
    637        BOUNDCHECK(ZSTD_c_targetLength, value);
    638        CCtxParams->cParams.targetLength = value;
    639        return CCtxParams->cParams.targetLength;
    640
    641    case ZSTD_c_strategy :
    642        if (value!=0)   /* 0 => use default */
    643            BOUNDCHECK(ZSTD_c_strategy, value);
    644        CCtxParams->cParams.strategy = (ZSTD_strategy)value;
    645        return (size_t)CCtxParams->cParams.strategy;
    646
    647    case ZSTD_c_contentSizeFlag :
    648        /* Content size written in frame header _when known_ (default:1) */
    649        DEBUGLOG(4, "set content size flag = %u", (value!=0));
    650        CCtxParams->fParams.contentSizeFlag = value != 0;
    651        return CCtxParams->fParams.contentSizeFlag;
    652
    653    case ZSTD_c_checksumFlag :
    654        /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
    655        CCtxParams->fParams.checksumFlag = value != 0;
    656        return CCtxParams->fParams.checksumFlag;
    657
    658    case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
    659        DEBUGLOG(4, "set dictIDFlag = %u", (value!=0));
    660        CCtxParams->fParams.noDictIDFlag = !value;
    661        return !CCtxParams->fParams.noDictIDFlag;
    662
    663    case ZSTD_c_forceMaxWindow :
    664        CCtxParams->forceWindow = (value != 0);
    665        return CCtxParams->forceWindow;
    666
    667    case ZSTD_c_forceAttachDict : {
    668        const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;
    669        BOUNDCHECK(ZSTD_c_forceAttachDict, pref);
    670        CCtxParams->attachDictPref = pref;
    671        return CCtxParams->attachDictPref;
    672    }
    673
    674    case ZSTD_c_literalCompressionMode : {
    675        const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
    676        BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
    677        CCtxParams->literalCompressionMode = lcm;
    678        return CCtxParams->literalCompressionMode;
    679    }
    680
    681    case ZSTD_c_nbWorkers :
    682        RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
    683        return 0;
    684
    685    case ZSTD_c_jobSize :
    686        RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
    687        return 0;
    688
    689    case ZSTD_c_overlapLog :
    690        RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
    691        return 0;
    692
    693    case ZSTD_c_rsyncable :
    694        RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
    695        return 0;
    696
    697    case ZSTD_c_enableDedicatedDictSearch :
    698        CCtxParams->enableDedicatedDictSearch = (value!=0);
    699        return CCtxParams->enableDedicatedDictSearch;
    700
    701    case ZSTD_c_enableLongDistanceMatching :
    702        CCtxParams->ldmParams.enableLdm = (value!=0);
    703        return CCtxParams->ldmParams.enableLdm;
    704
    705    case ZSTD_c_ldmHashLog :
    706        if (value!=0)   /* 0 ==> auto */
    707            BOUNDCHECK(ZSTD_c_ldmHashLog, value);
    708        CCtxParams->ldmParams.hashLog = value;
    709        return CCtxParams->ldmParams.hashLog;
    710
    711    case ZSTD_c_ldmMinMatch :
    712        if (value!=0)   /* 0 ==> default */
    713            BOUNDCHECK(ZSTD_c_ldmMinMatch, value);
    714        CCtxParams->ldmParams.minMatchLength = value;
    715        return CCtxParams->ldmParams.minMatchLength;
    716
    717    case ZSTD_c_ldmBucketSizeLog :
    718        if (value!=0)   /* 0 ==> default */
    719            BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value);
    720        CCtxParams->ldmParams.bucketSizeLog = value;
    721        return CCtxParams->ldmParams.bucketSizeLog;
    722
    723    case ZSTD_c_ldmHashRateLog :
    724        if (value!=0)   /* 0 ==> default */
    725            BOUNDCHECK(ZSTD_c_ldmHashRateLog, value);
    726        CCtxParams->ldmParams.hashRateLog = value;
    727        return CCtxParams->ldmParams.hashRateLog;
    728
    729    case ZSTD_c_targetCBlockSize :
    730        if (value!=0)   /* 0 ==> default */
    731            BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
    732        CCtxParams->targetCBlockSize = value;
    733        return CCtxParams->targetCBlockSize;
    734
    735    case ZSTD_c_srcSizeHint :
    736        if (value!=0)    /* 0 ==> default */
    737            BOUNDCHECK(ZSTD_c_srcSizeHint, value);
    738        CCtxParams->srcSizeHint = value;
    739        return CCtxParams->srcSizeHint;
    740
    741    case ZSTD_c_stableInBuffer:
    742        BOUNDCHECK(ZSTD_c_stableInBuffer, value);
    743        CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value;
    744        return CCtxParams->inBufferMode;
    745
    746    case ZSTD_c_stableOutBuffer:
    747        BOUNDCHECK(ZSTD_c_stableOutBuffer, value);
    748        CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value;
    749        return CCtxParams->outBufferMode;
    750
    751    case ZSTD_c_blockDelimiters:
    752        BOUNDCHECK(ZSTD_c_blockDelimiters, value);
    753        CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value;
    754        return CCtxParams->blockDelimiters;
    755
    756    case ZSTD_c_validateSequences:
    757        BOUNDCHECK(ZSTD_c_validateSequences, value);
    758        CCtxParams->validateSequences = value;
    759        return CCtxParams->validateSequences;
    760
    761    default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
    762    }
    763}
    764
    765size_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value)
    766{
    767    return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
    768}
    769
    770size_t ZSTD_CCtxParams_getParameter(
    771        ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value)
    772{
    773    switch(param)
    774    {
    775    case ZSTD_c_format :
    776        *value = CCtxParams->format;
    777        break;
    778    case ZSTD_c_compressionLevel :
    779        *value = CCtxParams->compressionLevel;
    780        break;
    781    case ZSTD_c_windowLog :
    782        *value = (int)CCtxParams->cParams.windowLog;
    783        break;
    784    case ZSTD_c_hashLog :
    785        *value = (int)CCtxParams->cParams.hashLog;
    786        break;
    787    case ZSTD_c_chainLog :
    788        *value = (int)CCtxParams->cParams.chainLog;
    789        break;
    790    case ZSTD_c_searchLog :
    791        *value = CCtxParams->cParams.searchLog;
    792        break;
    793    case ZSTD_c_minMatch :
    794        *value = CCtxParams->cParams.minMatch;
    795        break;
    796    case ZSTD_c_targetLength :
    797        *value = CCtxParams->cParams.targetLength;
    798        break;
    799    case ZSTD_c_strategy :
    800        *value = (unsigned)CCtxParams->cParams.strategy;
    801        break;
    802    case ZSTD_c_contentSizeFlag :
    803        *value = CCtxParams->fParams.contentSizeFlag;
    804        break;
    805    case ZSTD_c_checksumFlag :
    806        *value = CCtxParams->fParams.checksumFlag;
    807        break;
    808    case ZSTD_c_dictIDFlag :
    809        *value = !CCtxParams->fParams.noDictIDFlag;
    810        break;
    811    case ZSTD_c_forceMaxWindow :
    812        *value = CCtxParams->forceWindow;
    813        break;
    814    case ZSTD_c_forceAttachDict :
    815        *value = CCtxParams->attachDictPref;
    816        break;
    817    case ZSTD_c_literalCompressionMode :
    818        *value = CCtxParams->literalCompressionMode;
    819        break;
    820    case ZSTD_c_nbWorkers :
    821        assert(CCtxParams->nbWorkers == 0);
    822        *value = CCtxParams->nbWorkers;
    823        break;
    824    case ZSTD_c_jobSize :
    825        RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
    826    case ZSTD_c_overlapLog :
    827        RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
    828    case ZSTD_c_rsyncable :
    829        RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
    830    case ZSTD_c_enableDedicatedDictSearch :
    831        *value = CCtxParams->enableDedicatedDictSearch;
    832        break;
    833    case ZSTD_c_enableLongDistanceMatching :
    834        *value = CCtxParams->ldmParams.enableLdm;
    835        break;
    836    case ZSTD_c_ldmHashLog :
    837        *value = CCtxParams->ldmParams.hashLog;
    838        break;
    839    case ZSTD_c_ldmMinMatch :
    840        *value = CCtxParams->ldmParams.minMatchLength;
    841        break;
    842    case ZSTD_c_ldmBucketSizeLog :
    843        *value = CCtxParams->ldmParams.bucketSizeLog;
    844        break;
    845    case ZSTD_c_ldmHashRateLog :
    846        *value = CCtxParams->ldmParams.hashRateLog;
    847        break;
    848    case ZSTD_c_targetCBlockSize :
    849        *value = (int)CCtxParams->targetCBlockSize;
    850        break;
    851    case ZSTD_c_srcSizeHint :
    852        *value = (int)CCtxParams->srcSizeHint;
    853        break;
    854    case ZSTD_c_stableInBuffer :
    855        *value = (int)CCtxParams->inBufferMode;
    856        break;
    857    case ZSTD_c_stableOutBuffer :
    858        *value = (int)CCtxParams->outBufferMode;
    859        break;
    860    case ZSTD_c_blockDelimiters :
    861        *value = (int)CCtxParams->blockDelimiters;
    862        break;
    863    case ZSTD_c_validateSequences :
    864        *value = (int)CCtxParams->validateSequences;
    865        break;
    866    default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
    867    }
    868    return 0;
    869}
    870
    871/* ZSTD_CCtx_setParametersUsingCCtxParams() :
    872 *  just applies `params` into `cctx`
    873 *  no action is performed, parameters are merely stored.
    874 *  If ZSTDMT is enabled, parameters are pushed to cctx->mtctx.
    875 *    This is possible even if a compression is ongoing.
    876 *    In which case, new parameters will be applied on the fly, starting with next compression job.
    877 */
    878size_t ZSTD_CCtx_setParametersUsingCCtxParams(
    879        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
    880{
    881    DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
    882    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
    883                    "The context is in the wrong stage!");
    884    RETURN_ERROR_IF(cctx->cdict, stage_wrong,
    885                    "Can't override parameters with cdict attached (some must "
    886                    "be inherited from the cdict).");
    887
    888    cctx->requestedParams = *params;
    889    return 0;
    890}
    891
    892ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
    893{
    894    DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
    895    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
    896                    "Can't set pledgedSrcSize when not in init stage.");
    897    cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
    898    return 0;
    899}
    900
    901static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(
    902        int const compressionLevel,
    903        size_t const dictSize);
    904static int ZSTD_dedicatedDictSearch_isSupported(
    905        const ZSTD_compressionParameters* cParams);
    906static void ZSTD_dedicatedDictSearch_revertCParams(
    907        ZSTD_compressionParameters* cParams);
    908
    909/*
    910 * Initializes the local dict using the requested parameters.
    911 * NOTE: This does not use the pledged src size, because it may be used for more
    912 * than one compression.
    913 */
    914static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
    915{
    916    ZSTD_localDict* const dl = &cctx->localDict;
    917    if (dl->dict == NULL) {
    918        /* No local dictionary. */
    919        assert(dl->dictBuffer == NULL);
    920        assert(dl->cdict == NULL);
    921        assert(dl->dictSize == 0);
    922        return 0;
    923    }
    924    if (dl->cdict != NULL) {
    925        assert(cctx->cdict == dl->cdict);
    926        /* Local dictionary already initialized. */
    927        return 0;
    928    }
    929    assert(dl->dictSize > 0);
    930    assert(cctx->cdict == NULL);
    931    assert(cctx->prefixDict.dict == NULL);
    932
    933    dl->cdict = ZSTD_createCDict_advanced2(
    934            dl->dict,
    935            dl->dictSize,
    936            ZSTD_dlm_byRef,
    937            dl->dictContentType,
    938            &cctx->requestedParams,
    939            cctx->customMem);
    940    RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
    941    cctx->cdict = dl->cdict;
    942    return 0;
    943}
    944
    945size_t ZSTD_CCtx_loadDictionary_advanced(
    946        ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
    947        ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
    948{
    949    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
    950                    "Can't load a dictionary when ctx is not in init stage.");
    951    DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
    952    ZSTD_clearAllDicts(cctx);  /* in case one already exists */
    953    if (dict == NULL || dictSize == 0)  /* no dictionary mode */
    954        return 0;
    955    if (dictLoadMethod == ZSTD_dlm_byRef) {
    956        cctx->localDict.dict = dict;
    957    } else {
    958        void* dictBuffer;
    959        RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
    960                        "no malloc for static CCtx");
    961        dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem);
    962        RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
    963        ZSTD_memcpy(dictBuffer, dict, dictSize);
    964        cctx->localDict.dictBuffer = dictBuffer;
    965        cctx->localDict.dict = dictBuffer;
    966    }
    967    cctx->localDict.dictSize = dictSize;
    968    cctx->localDict.dictContentType = dictContentType;
    969    return 0;
    970}
    971
    972ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
    973      ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
    974{
    975    return ZSTD_CCtx_loadDictionary_advanced(
    976            cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
    977}
    978
    979ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
    980{
    981    return ZSTD_CCtx_loadDictionary_advanced(
    982            cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
    983}
    984
    985
    986size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
    987{
    988    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
    989                    "Can't ref a dict when ctx not in init stage.");
    990    /* Free the existing local cdict (if any) to save memory. */
    991    ZSTD_clearAllDicts(cctx);
    992    cctx->cdict = cdict;
    993    return 0;
    994}
    995
    996size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool)
    997{
    998    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
    999                    "Can't ref a pool when ctx not in init stage.");
   1000    cctx->pool = pool;
   1001    return 0;
   1002}
   1003
   1004size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
   1005{
   1006    return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);
   1007}
   1008
   1009size_t ZSTD_CCtx_refPrefix_advanced(
   1010        ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
   1011{
   1012    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
   1013                    "Can't ref a prefix when ctx not in init stage.");
   1014    ZSTD_clearAllDicts(cctx);
   1015    if (prefix != NULL && prefixSize > 0) {
   1016        cctx->prefixDict.dict = prefix;
   1017        cctx->prefixDict.dictSize = prefixSize;
   1018        cctx->prefixDict.dictContentType = dictContentType;
   1019    }
   1020    return 0;
   1021}
   1022
   1023/*! ZSTD_CCtx_reset() :
   1024 *  Also dumps dictionary */
   1025size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
   1026{
   1027    if ( (reset == ZSTD_reset_session_only)
   1028      || (reset == ZSTD_reset_session_and_parameters) ) {
   1029        cctx->streamStage = zcss_init;
   1030        cctx->pledgedSrcSizePlusOne = 0;
   1031    }
   1032    if ( (reset == ZSTD_reset_parameters)
   1033      || (reset == ZSTD_reset_session_and_parameters) ) {
   1034        RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
   1035                        "Can't reset parameters only when not in init stage.");
   1036        ZSTD_clearAllDicts(cctx);
   1037        return ZSTD_CCtxParams_reset(&cctx->requestedParams);
   1038    }
   1039    return 0;
   1040}
   1041
   1042
   1043/* ZSTD_checkCParams() :
   1044    control CParam values remain within authorized range.
   1045    @return : 0, or an error code if one value is beyond authorized range */
   1046size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
   1047{
   1048    BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);
   1049    BOUNDCHECK(ZSTD_c_chainLog,  (int)cParams.chainLog);
   1050    BOUNDCHECK(ZSTD_c_hashLog,   (int)cParams.hashLog);
   1051    BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);
   1052    BOUNDCHECK(ZSTD_c_minMatch,  (int)cParams.minMatch);
   1053    BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);
   1054    BOUNDCHECK(ZSTD_c_strategy,  cParams.strategy);
   1055    return 0;
   1056}
   1057
   1058/* ZSTD_clampCParams() :
   1059 *  make CParam values within valid range.
   1060 *  @return : valid CParams */
   1061static ZSTD_compressionParameters
   1062ZSTD_clampCParams(ZSTD_compressionParameters cParams)
   1063{
   1064#   define CLAMP_TYPE(cParam, val, type) {                                \
   1065        ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);         \
   1066        if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound;      \
   1067        else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
   1068    }
   1069#   define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
   1070    CLAMP(ZSTD_c_windowLog, cParams.windowLog);
   1071    CLAMP(ZSTD_c_chainLog,  cParams.chainLog);
   1072    CLAMP(ZSTD_c_hashLog,   cParams.hashLog);
   1073    CLAMP(ZSTD_c_searchLog, cParams.searchLog);
   1074    CLAMP(ZSTD_c_minMatch,  cParams.minMatch);
   1075    CLAMP(ZSTD_c_targetLength,cParams.targetLength);
   1076    CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy);
   1077    return cParams;
   1078}
   1079
   1080/* ZSTD_cycleLog() :
   1081 *  condition for correct operation : hashLog > 1 */
   1082U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
   1083{
   1084    U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
   1085    return hashLog - btScale;
   1086}
   1087
   1088/* ZSTD_dictAndWindowLog() :
   1089 * Returns an adjusted window log that is large enough to fit the source and the dictionary.
   1090 * The zstd format says that the entire dictionary is valid if one byte of the dictionary
   1091 * is within the window. So the hashLog and chainLog should be large enough to reference both
   1092 * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing
   1093 * the hashLog and windowLog.
   1094 * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN.
   1095 */
   1096static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)
   1097{
   1098    const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX;
   1099    /* No dictionary ==> No change */
   1100    if (dictSize == 0) {
   1101        return windowLog;
   1102    }
   1103    assert(windowLog <= ZSTD_WINDOWLOG_MAX);
   1104    assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */
   1105    {
   1106        U64 const windowSize = 1ULL << windowLog;
   1107        U64 const dictAndWindowSize = dictSize + windowSize;
   1108        /* If the window size is already large enough to fit both the source and the dictionary
   1109         * then just use the window size. Otherwise adjust so that it fits the dictionary and
   1110         * the window.
   1111         */
   1112        if (windowSize >= dictSize + srcSize) {
   1113            return windowLog; /* Window size large enough already */
   1114        } else if (dictAndWindowSize >= maxWindowSize) {
   1115            return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */
   1116        } else  {
   1117            return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1;
   1118        }
   1119    }
   1120}
   1121
   1122/* ZSTD_adjustCParams_internal() :
   1123 *  optimize `cPar` for a specified input (`srcSize` and `dictSize`).
   1124 *  mostly downsize to reduce memory consumption and initialization latency.
   1125 * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
   1126 * `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`.
   1127 *  note : `srcSize==0` means 0!
   1128 *  condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
   1129static ZSTD_compressionParameters
   1130ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
   1131                            unsigned long long srcSize,
   1132                            size_t dictSize,
   1133                            ZSTD_cParamMode_e mode)
   1134{
   1135    const U64 minSrcSize = 513; /* (1<<9) + 1 */
   1136    const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
   1137    assert(ZSTD_checkCParams(cPar)==0);
   1138
   1139    switch (mode) {
   1140    case ZSTD_cpm_unknown:
   1141    case ZSTD_cpm_noAttachDict:
   1142        /* If we don't know the source size, don't make any
   1143         * assumptions about it. We will already have selected
   1144         * smaller parameters if a dictionary is in use.
   1145         */
   1146        break;
   1147    case ZSTD_cpm_createCDict:
   1148        /* Assume a small source size when creating a dictionary
   1149         * with an unkown source size.
   1150         */
   1151        if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
   1152            srcSize = minSrcSize;
   1153        break;
   1154    case ZSTD_cpm_attachDict:
   1155        /* Dictionary has its own dedicated parameters which have
   1156         * already been selected. We are selecting parameters
   1157         * for only the source.
   1158         */
   1159        dictSize = 0;
   1160        break;
   1161    default:
   1162        assert(0);
   1163        break;
   1164    }
   1165
   1166    /* resize windowLog if input is small enough, to use less memory */
   1167    if ( (srcSize < maxWindowResize)
   1168      && (dictSize < maxWindowResize) )  {
   1169        U32 const tSize = (U32)(srcSize + dictSize);
   1170        static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
   1171        U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
   1172                            ZSTD_highbit32(tSize-1) + 1;
   1173        if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
   1174    }
   1175    if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
   1176        U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize);
   1177        U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
   1178        if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1;
   1179        if (cycleLog > dictAndWindowLog)
   1180            cPar.chainLog -= (cycleLog - dictAndWindowLog);
   1181    }
   1182
   1183    if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
   1184        cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN;  /* minimum wlog required for valid frame header */
   1185
   1186    return cPar;
   1187}
   1188
   1189ZSTD_compressionParameters
   1190ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
   1191                   unsigned long long srcSize,
   1192                   size_t dictSize)
   1193{
   1194    cPar = ZSTD_clampCParams(cPar);   /* resulting cPar is necessarily valid (all parameters within range) */
   1195    if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
   1196    return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown);
   1197}
   1198
   1199static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
   1200static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
   1201
   1202static void ZSTD_overrideCParams(
   1203              ZSTD_compressionParameters* cParams,
   1204        const ZSTD_compressionParameters* overrides)
   1205{
   1206    if (overrides->windowLog)    cParams->windowLog    = overrides->windowLog;
   1207    if (overrides->hashLog)      cParams->hashLog      = overrides->hashLog;
   1208    if (overrides->chainLog)     cParams->chainLog     = overrides->chainLog;
   1209    if (overrides->searchLog)    cParams->searchLog    = overrides->searchLog;
   1210    if (overrides->minMatch)     cParams->minMatch     = overrides->minMatch;
   1211    if (overrides->targetLength) cParams->targetLength = overrides->targetLength;
   1212    if (overrides->strategy)     cParams->strategy     = overrides->strategy;
   1213}
   1214
   1215ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
   1216        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
   1217{
   1218    ZSTD_compressionParameters cParams;
   1219    if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
   1220      srcSizeHint = CCtxParams->srcSizeHint;
   1221    }
   1222    cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);
   1223    if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
   1224    ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);
   1225    assert(!ZSTD_checkCParams(cParams));
   1226    /* srcSizeHint == 0 means 0 */
   1227    return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode);
   1228}
   1229
   1230static size_t
   1231ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
   1232                       const U32 forCCtx)
   1233{
   1234    size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
   1235    size_t const hSize = ((size_t)1) << cParams->hashLog;
   1236    U32    const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
   1237    size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
   1238    /* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't
   1239     * surrounded by redzones in ASAN. */
   1240    size_t const tableSpace = chainSize * sizeof(U32)
   1241                            + hSize * sizeof(U32)
   1242                            + h3Size * sizeof(U32);
   1243    size_t const optPotentialSpace =
   1244        ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32))
   1245      + ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32))
   1246      + ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32))
   1247      + ZSTD_cwksp_alloc_size((1<<Litbits) * sizeof(U32))
   1248      + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
   1249      + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
   1250    size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
   1251                                ? optPotentialSpace
   1252                                : 0;
   1253    DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
   1254                (U32)chainSize, (U32)hSize, (U32)h3Size);
   1255    return tableSpace + optSpace;
   1256}
   1257
   1258static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
   1259        const ZSTD_compressionParameters* cParams,
   1260        const ldmParams_t* ldmParams,
   1261        const int isStatic,
   1262        const size_t buffInSize,
   1263        const size_t buffOutSize,
   1264        const U64 pledgedSrcSize)
   1265{
   1266    size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize));
   1267    size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
   1268    U32    const divider = (cParams->minMatch==3) ? 3 : 4;
   1269    size_t const maxNbSeq = blockSize / divider;
   1270    size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
   1271                            + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
   1272                            + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
   1273    size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE);
   1274    size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
   1275    size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, /* forCCtx */ 1);
   1276
   1277    size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);
   1278    size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);
   1279    size_t const ldmSeqSpace = ldmParams->enableLdm ?
   1280        ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;
   1281
   1282
   1283    size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize)
   1284                             + ZSTD_cwksp_alloc_size(buffOutSize);
   1285
   1286    size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
   1287
   1288    size_t const neededSpace =
   1289        cctxSpace +
   1290        entropySpace +
   1291        blockStateSpace +
   1292        ldmSpace +
   1293        ldmSeqSpace +
   1294        matchStateSize +
   1295        tokenSpace +
   1296        bufferSpace;
   1297
   1298    DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
   1299    return neededSpace;
   1300}
   1301
   1302size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
   1303{
   1304    ZSTD_compressionParameters const cParams =
   1305                ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
   1306
   1307    RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
   1308    /* estimateCCtxSize is for one-shot compression. So no buffers should
   1309     * be needed. However, we still allocate two 0-sized buffers, which can
   1310     * take space under ASAN. */
   1311    return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
   1312        &cParams, &params->ldmParams, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN);
   1313}
   1314
   1315size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
   1316{
   1317    ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
   1318    return ZSTD_estimateCCtxSize_usingCCtxParams(&params);
   1319}
   1320
   1321static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
   1322{
   1323    int tier = 0;
   1324    size_t largestSize = 0;
   1325    static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN};
   1326    for (; tier < 4; ++tier) {
   1327        /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */
   1328        ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict);
   1329        largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize);
   1330    }
   1331    return largestSize;
   1332}
   1333
   1334size_t ZSTD_estimateCCtxSize(int compressionLevel)
   1335{
   1336    int level;
   1337    size_t memBudget = 0;
   1338    for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
   1339        /* Ensure monotonically increasing memory usage as compression level increases */
   1340        size_t const newMB = ZSTD_estimateCCtxSize_internal(level);
   1341        if (newMB > memBudget) memBudget = newMB;
   1342    }
   1343    return memBudget;
   1344}
   1345
   1346size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
   1347{
   1348    RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
   1349    {   ZSTD_compressionParameters const cParams =
   1350                ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
   1351        size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
   1352        size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)
   1353                ? ((size_t)1 << cParams.windowLog) + blockSize
   1354                : 0;
   1355        size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)
   1356                ? ZSTD_compressBound(blockSize) + 1
   1357                : 0;
   1358
   1359        return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
   1360            &cParams, &params->ldmParams, 1, inBuffSize, outBuffSize,
   1361            ZSTD_CONTENTSIZE_UNKNOWN);
   1362    }
   1363}
   1364
   1365size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
   1366{
   1367    ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
   1368    return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
   1369}
   1370
   1371static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
   1372{
   1373    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
   1374    return ZSTD_estimateCStreamSize_usingCParams(cParams);
   1375}
   1376
   1377size_t ZSTD_estimateCStreamSize(int compressionLevel)
   1378{
   1379    int level;
   1380    size_t memBudget = 0;
   1381    for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
   1382        size_t const newMB = ZSTD_estimateCStreamSize_internal(level);
   1383        if (newMB > memBudget) memBudget = newMB;
   1384    }
   1385    return memBudget;
   1386}
   1387
   1388/* ZSTD_getFrameProgression():
   1389 * tells how much data has been consumed (input) and produced (output) for current frame.
   1390 * able to count progression inside worker threads (non-blocking mode).
   1391 */
   1392ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)
   1393{
   1394    {   ZSTD_frameProgression fp;
   1395        size_t const buffered = (cctx->inBuff == NULL) ? 0 :
   1396                                cctx->inBuffPos - cctx->inToCompress;
   1397        if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);
   1398        assert(buffered <= ZSTD_BLOCKSIZE_MAX);
   1399        fp.ingested = cctx->consumedSrcSize + buffered;
   1400        fp.consumed = cctx->consumedSrcSize;
   1401        fp.produced = cctx->producedCSize;
   1402        fp.flushed  = cctx->producedCSize;   /* simplified; some data might still be left within streaming output buffer */
   1403        fp.currentJobID = 0;
   1404        fp.nbActiveWorkers = 0;
   1405        return fp;
   1406}   }
   1407
   1408/*! ZSTD_toFlushNow()
   1409 *  Only useful for multithreading scenarios currently (nbWorkers >= 1).
   1410 */
   1411size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
   1412{
   1413    (void)cctx;
   1414    return 0;   /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */
   1415}
   1416
   1417static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
   1418                                    ZSTD_compressionParameters cParams2)
   1419{
   1420    (void)cParams1;
   1421    (void)cParams2;
   1422    assert(cParams1.windowLog    == cParams2.windowLog);
   1423    assert(cParams1.chainLog     == cParams2.chainLog);
   1424    assert(cParams1.hashLog      == cParams2.hashLog);
   1425    assert(cParams1.searchLog    == cParams2.searchLog);
   1426    assert(cParams1.minMatch     == cParams2.minMatch);
   1427    assert(cParams1.targetLength == cParams2.targetLength);
   1428    assert(cParams1.strategy     == cParams2.strategy);
   1429}
   1430
   1431void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
   1432{
   1433    int i;
   1434    for (i = 0; i < ZSTD_REP_NUM; ++i)
   1435        bs->rep[i] = repStartValue[i];
   1436    bs->entropy.huf.repeatMode = HUF_repeat_none;
   1437    bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;
   1438    bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;
   1439    bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;
   1440}
   1441
   1442/*! ZSTD_invalidateMatchState()
   1443 *  Invalidate all the matches in the match finder tables.
   1444 *  Requires nextSrc and base to be set (can be NULL).
   1445 */
   1446static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
   1447{
   1448    ZSTD_window_clear(&ms->window);
   1449
   1450    ms->nextToUpdate = ms->window.dictLimit;
   1451    ms->loadedDictEnd = 0;
   1452    ms->opt.litLengthSum = 0;  /* force reset of btopt stats */
   1453    ms->dictMatchState = NULL;
   1454}
   1455
   1456/*
   1457 * Controls, for this matchState reset, whether the tables need to be cleared /
   1458 * prepared for the coming compression (ZSTDcrp_makeClean), or whether the
   1459 * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a
   1460 * subsequent operation will overwrite the table space anyways (e.g., copying
   1461 * the matchState contents in from a CDict).
   1462 */
   1463typedef enum {
   1464    ZSTDcrp_makeClean,
   1465    ZSTDcrp_leaveDirty
   1466} ZSTD_compResetPolicy_e;
   1467
   1468/*
   1469 * Controls, for this matchState reset, whether indexing can continue where it
   1470 * left off (ZSTDirp_continue), or whether it needs to be restarted from zero
   1471 * (ZSTDirp_reset).
   1472 */
   1473typedef enum {
   1474    ZSTDirp_continue,
   1475    ZSTDirp_reset
   1476} ZSTD_indexResetPolicy_e;
   1477
   1478typedef enum {
   1479    ZSTD_resetTarget_CDict,
   1480    ZSTD_resetTarget_CCtx
   1481} ZSTD_resetTarget_e;
   1482
   1483static size_t
   1484ZSTD_reset_matchState(ZSTD_matchState_t* ms,
   1485                      ZSTD_cwksp* ws,
   1486                const ZSTD_compressionParameters* cParams,
   1487                const ZSTD_compResetPolicy_e crp,
   1488                const ZSTD_indexResetPolicy_e forceResetIndex,
   1489                const ZSTD_resetTarget_e forWho)
   1490{
   1491    size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
   1492    size_t const hSize = ((size_t)1) << cParams->hashLog;
   1493    U32    const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
   1494    size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
   1495
   1496    DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset);
   1497    if (forceResetIndex == ZSTDirp_reset) {
   1498        ZSTD_window_init(&ms->window);
   1499        ZSTD_cwksp_mark_tables_dirty(ws);
   1500    }
   1501
   1502    ms->hashLog3 = hashLog3;
   1503
   1504    ZSTD_invalidateMatchState(ms);
   1505
   1506    assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */
   1507
   1508    ZSTD_cwksp_clear_tables(ws);
   1509
   1510    DEBUGLOG(5, "reserving table space");
   1511    /* table Space */
   1512    ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32));
   1513    ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32));
   1514    ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32));
   1515    RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
   1516                    "failed a workspace allocation in ZSTD_reset_matchState");
   1517
   1518    DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_leaveDirty);
   1519    if (crp!=ZSTDcrp_leaveDirty) {
   1520        /* reset tables only */
   1521        ZSTD_cwksp_clean_tables(ws);
   1522    }
   1523
   1524    /* opt parser space */
   1525    if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
   1526        DEBUGLOG(4, "reserving optimal parser space");
   1527        ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<<Litbits) * sizeof(unsigned));
   1528        ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned));
   1529        ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned));
   1530        ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned));
   1531        ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t));
   1532        ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
   1533    }
   1534
   1535    ms->cParams = *cParams;
   1536
   1537    RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
   1538                    "failed a workspace allocation in ZSTD_reset_matchState");
   1539
   1540    return 0;
   1541}
   1542
   1543/* ZSTD_indexTooCloseToMax() :
   1544 * minor optimization : prefer memset() rather than reduceIndex()
   1545 * which is measurably slow in some circumstances (reported for Visual Studio).
   1546 * Works when re-using a context for a lot of smallish inputs :
   1547 * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,
   1548 * memset() will be triggered before reduceIndex().
   1549 */
   1550#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)
   1551static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
   1552{
   1553    return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
   1554}
   1555
   1556/*! ZSTD_resetCCtx_internal() :
   1557    note : `params` are assumed fully validated at this stage */
   1558static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
   1559                                      ZSTD_CCtx_params params,
   1560                                      U64 const pledgedSrcSize,
   1561                                      ZSTD_compResetPolicy_e const crp,
   1562                                      ZSTD_buffered_policy_e const zbuff)
   1563{
   1564    ZSTD_cwksp* const ws = &zc->workspace;
   1565    DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
   1566                (U32)pledgedSrcSize, params.cParams.windowLog);
   1567    assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
   1568
   1569    zc->isFirstBlock = 1;
   1570
   1571    if (params.ldmParams.enableLdm) {
   1572        /* Adjust long distance matching parameters */
   1573        ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
   1574        assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
   1575        assert(params.ldmParams.hashRateLog < 32);
   1576    }
   1577
   1578    {   size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
   1579        size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
   1580        U32    const divider = (params.cParams.minMatch==3) ? 3 : 4;
   1581        size_t const maxNbSeq = blockSize / divider;
   1582        size_t const buffOutSize = (zbuff == ZSTDb_buffered && params.outBufferMode == ZSTD_bm_buffered)
   1583                ? ZSTD_compressBound(blockSize) + 1
   1584                : 0;
   1585        size_t const buffInSize = (zbuff == ZSTDb_buffered && params.inBufferMode == ZSTD_bm_buffered)
   1586                ? windowSize + blockSize
   1587                : 0;
   1588        size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
   1589
   1590        int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window);
   1591        ZSTD_indexResetPolicy_e needsIndexReset =
   1592            (!indexTooClose && zc->initialized) ? ZSTDirp_continue : ZSTDirp_reset;
   1593
   1594        size_t const neededSpace =
   1595            ZSTD_estimateCCtxSize_usingCCtxParams_internal(
   1596                &params.cParams, &params.ldmParams, zc->staticSize != 0,
   1597                buffInSize, buffOutSize, pledgedSrcSize);
   1598        FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
   1599
   1600        if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
   1601
   1602        /* Check if workspace is large enough, alloc a new one if needed */
   1603        {
   1604            int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
   1605            int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
   1606
   1607            DEBUGLOG(4, "Need %zu B workspace", neededSpace);
   1608            DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
   1609
   1610            if (workspaceTooSmall || workspaceWasteful) {
   1611                DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
   1612                            ZSTD_cwksp_sizeof(ws) >> 10,
   1613                            neededSpace >> 10);
   1614
   1615                RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
   1616
   1617                needsIndexReset = ZSTDirp_reset;
   1618
   1619                ZSTD_cwksp_free(ws, zc->customMem);
   1620                FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), "");
   1621
   1622                DEBUGLOG(5, "reserving object space");
   1623                /* Statically sized space.
   1624                 * entropyWorkspace never moves,
   1625                 * though prev/next block swap places */
   1626                assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));
   1627                zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
   1628                RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
   1629                zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
   1630                RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
   1631                zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE);
   1632                RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
   1633        }   }
   1634
   1635        ZSTD_cwksp_clear(ws);
   1636
   1637        /* init params */
   1638        zc->appliedParams = params;
   1639        zc->blockState.matchState.cParams = params.cParams;
   1640        zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
   1641        zc->consumedSrcSize = 0;
   1642        zc->producedCSize = 0;
   1643        if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
   1644            zc->appliedParams.fParams.contentSizeFlag = 0;
   1645        DEBUGLOG(4, "pledged content size : %u ; flag : %u",
   1646            (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
   1647        zc->blockSize = blockSize;
   1648
   1649        xxh64_reset(&zc->xxhState, 0);
   1650        zc->stage = ZSTDcs_init;
   1651        zc->dictID = 0;
   1652        zc->dictContentSize = 0;
   1653
   1654        ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
   1655
   1656        /* ZSTD_wildcopy() is used to copy into the literals buffer,
   1657         * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
   1658         */
   1659        zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);
   1660        zc->seqStore.maxNbLit = blockSize;
   1661
   1662        /* buffers */
   1663        zc->bufferedPolicy = zbuff;
   1664        zc->inBuffSize = buffInSize;
   1665        zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);
   1666        zc->outBuffSize = buffOutSize;
   1667        zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);
   1668
   1669        /* ldm bucketOffsets table */
   1670        if (params.ldmParams.enableLdm) {
   1671            /* TODO: avoid memset? */
   1672            size_t const numBuckets =
   1673                  ((size_t)1) << (params.ldmParams.hashLog -
   1674                                  params.ldmParams.bucketSizeLog);
   1675            zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets);
   1676            ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets);
   1677        }
   1678
   1679        /* sequences storage */
   1680        ZSTD_referenceExternalSequences(zc, NULL, 0);
   1681        zc->seqStore.maxNbSeq = maxNbSeq;
   1682        zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
   1683        zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
   1684        zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
   1685        zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef));
   1686
   1687        FORWARD_IF_ERROR(ZSTD_reset_matchState(
   1688            &zc->blockState.matchState,
   1689            ws,
   1690            &params.cParams,
   1691            crp,
   1692            needsIndexReset,
   1693            ZSTD_resetTarget_CCtx), "");
   1694
   1695        /* ldm hash table */
   1696        if (params.ldmParams.enableLdm) {
   1697            /* TODO: avoid memset? */
   1698            size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
   1699            zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
   1700            ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
   1701            zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq));
   1702            zc->maxNbLdmSequences = maxNbLdmSeq;
   1703
   1704            ZSTD_window_init(&zc->ldmState.window);
   1705            ZSTD_window_clear(&zc->ldmState.window);
   1706            zc->ldmState.loadedDictEnd = 0;
   1707        }
   1708
   1709        /* Due to alignment, when reusing a workspace, we can actually consume
   1710         * up to 3 extra bytes for alignment. See the comments in zstd_cwksp.h
   1711         */
   1712        assert(ZSTD_cwksp_used(ws) >= neededSpace &&
   1713               ZSTD_cwksp_used(ws) <= neededSpace + 3);
   1714
   1715        DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
   1716        zc->initialized = 1;
   1717
   1718        return 0;
   1719    }
   1720}
   1721
   1722/* ZSTD_invalidateRepCodes() :
   1723 * ensures next compression will not use repcodes from previous block.
   1724 * Note : only works with regular variant;
   1725 *        do not use with extDict variant ! */
   1726void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
   1727    int i;
   1728    for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;
   1729    assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
   1730}
   1731
   1732/* These are the approximate sizes for each strategy past which copying the
   1733 * dictionary tables into the working context is faster than using them
   1734 * in-place.
   1735 */
   1736static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
   1737    8 KB,  /* unused */
   1738    8 KB,  /* ZSTD_fast */
   1739    16 KB, /* ZSTD_dfast */
   1740    32 KB, /* ZSTD_greedy */
   1741    32 KB, /* ZSTD_lazy */
   1742    32 KB, /* ZSTD_lazy2 */
   1743    32 KB, /* ZSTD_btlazy2 */
   1744    32 KB, /* ZSTD_btopt */
   1745    8 KB,  /* ZSTD_btultra */
   1746    8 KB   /* ZSTD_btultra2 */
   1747};
   1748
   1749static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
   1750                                 const ZSTD_CCtx_params* params,
   1751                                 U64 pledgedSrcSize)
   1752{
   1753    size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
   1754    int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch;
   1755    return dedicatedDictSearch
   1756        || ( ( pledgedSrcSize <= cutoff
   1757            || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
   1758            || params->attachDictPref == ZSTD_dictForceAttach )
   1759          && params->attachDictPref != ZSTD_dictForceCopy
   1760          && !params->forceWindow ); /* dictMatchState isn't correctly
   1761                                      * handled in _enforceMaxDist */
   1762}
   1763
   1764static size_t
   1765ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
   1766                        const ZSTD_CDict* cdict,
   1767                        ZSTD_CCtx_params params,
   1768                        U64 pledgedSrcSize,
   1769                        ZSTD_buffered_policy_e zbuff)
   1770{
   1771    {
   1772        ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams;
   1773        unsigned const windowLog = params.cParams.windowLog;
   1774        assert(windowLog != 0);
   1775        /* Resize working context table params for input only, since the dict
   1776         * has its own tables. */
   1777        /* pledgedSrcSize == 0 means 0! */
   1778
   1779        if (cdict->matchState.dedicatedDictSearch) {
   1780            ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams);
   1781        }
   1782
   1783        params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,
   1784                                                     cdict->dictContentSize, ZSTD_cpm_attachDict);
   1785        params.cParams.windowLog = windowLog;
   1786        FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
   1787                                                 ZSTDcrp_makeClean, zbuff), "");
   1788        assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy);
   1789    }
   1790
   1791    {   const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
   1792                                  - cdict->matchState.window.base);
   1793        const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
   1794        if (cdictLen == 0) {
   1795            /* don't even attach dictionaries with no contents */
   1796            DEBUGLOG(4, "skipping attaching empty dictionary");
   1797        } else {
   1798            DEBUGLOG(4, "attaching dictionary into context");
   1799            cctx->blockState.matchState.dictMatchState = &cdict->matchState;
   1800
   1801            /* prep working match state so dict matches never have negative indices
   1802             * when they are translated to the working context's index space. */
   1803            if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {
   1804                cctx->blockState.matchState.window.nextSrc =
   1805                    cctx->blockState.matchState.window.base + cdictEnd;
   1806                ZSTD_window_clear(&cctx->blockState.matchState.window);
   1807            }
   1808            /* loadedDictEnd is expressed within the referential of the active context */
   1809            cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
   1810    }   }
   1811
   1812    cctx->dictID = cdict->dictID;
   1813    cctx->dictContentSize = cdict->dictContentSize;
   1814
   1815    /* copy block state */
   1816    ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
   1817
   1818    return 0;
   1819}
   1820
   1821static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
   1822                            const ZSTD_CDict* cdict,
   1823                            ZSTD_CCtx_params params,
   1824                            U64 pledgedSrcSize,
   1825                            ZSTD_buffered_policy_e zbuff)
   1826{
   1827    const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
   1828
   1829    assert(!cdict->matchState.dedicatedDictSearch);
   1830
   1831    DEBUGLOG(4, "copying dictionary into context");
   1832
   1833    {   unsigned const windowLog = params.cParams.windowLog;
   1834        assert(windowLog != 0);
   1835        /* Copy only compression parameters related to tables. */
   1836        params.cParams = *cdict_cParams;
   1837        params.cParams.windowLog = windowLog;
   1838        FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
   1839                                                 ZSTDcrp_leaveDirty, zbuff), "");
   1840        assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
   1841        assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
   1842        assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
   1843    }
   1844
   1845    ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
   1846
   1847    /* copy tables */
   1848    {   size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
   1849        size_t const hSize =  (size_t)1 << cdict_cParams->hashLog;
   1850
   1851        ZSTD_memcpy(cctx->blockState.matchState.hashTable,
   1852               cdict->matchState.hashTable,
   1853               hSize * sizeof(U32));
   1854        ZSTD_memcpy(cctx->blockState.matchState.chainTable,
   1855               cdict->matchState.chainTable,
   1856               chainSize * sizeof(U32));
   1857    }
   1858
   1859    /* Zero the hashTable3, since the cdict never fills it */
   1860    {   int const h3log = cctx->blockState.matchState.hashLog3;
   1861        size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
   1862        assert(cdict->matchState.hashLog3 == 0);
   1863        ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
   1864    }
   1865
   1866    ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
   1867
   1868    /* copy dictionary offsets */
   1869    {   ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
   1870        ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
   1871        dstMatchState->window       = srcMatchState->window;
   1872        dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
   1873        dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
   1874    }
   1875
   1876    cctx->dictID = cdict->dictID;
   1877    cctx->dictContentSize = cdict->dictContentSize;
   1878
   1879    /* copy block state */
   1880    ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
   1881
   1882    return 0;
   1883}
   1884
   1885/* We have a choice between copying the dictionary context into the working
   1886 * context, or referencing the dictionary context from the working context
   1887 * in-place. We decide here which strategy to use. */
   1888static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
   1889                            const ZSTD_CDict* cdict,
   1890                            const ZSTD_CCtx_params* params,
   1891                            U64 pledgedSrcSize,
   1892                            ZSTD_buffered_policy_e zbuff)
   1893{
   1894
   1895    DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)",
   1896                (unsigned)pledgedSrcSize);
   1897
   1898    if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
   1899        return ZSTD_resetCCtx_byAttachingCDict(
   1900            cctx, cdict, *params, pledgedSrcSize, zbuff);
   1901    } else {
   1902        return ZSTD_resetCCtx_byCopyingCDict(
   1903            cctx, cdict, *params, pledgedSrcSize, zbuff);
   1904    }
   1905}
   1906
   1907/*! ZSTD_copyCCtx_internal() :
   1908 *  Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
   1909 *  Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
   1910 *  The "context", in this case, refers to the hash and chain tables,
   1911 *  entropy tables, and dictionary references.
   1912 * `windowLog` value is enforced if != 0, otherwise value is copied from srcCCtx.
   1913 * @return : 0, or an error code */
   1914static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
   1915                            const ZSTD_CCtx* srcCCtx,
   1916                            ZSTD_frameParameters fParams,
   1917                            U64 pledgedSrcSize,
   1918                            ZSTD_buffered_policy_e zbuff)
   1919{
   1920    DEBUGLOG(5, "ZSTD_copyCCtx_internal");
   1921    RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
   1922                    "Can't copy a ctx that's not in init stage.");
   1923
   1924    ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
   1925    {   ZSTD_CCtx_params params = dstCCtx->requestedParams;
   1926        /* Copy only compression parameters related to tables. */
   1927        params.cParams = srcCCtx->appliedParams.cParams;
   1928        params.fParams = fParams;
   1929        ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
   1930                                ZSTDcrp_leaveDirty, zbuff);
   1931        assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
   1932        assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
   1933        assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
   1934        assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog);
   1935        assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
   1936    }
   1937
   1938    ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
   1939
   1940    /* copy tables */
   1941    {   size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
   1942        size_t const hSize =  (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
   1943        int const h3log = srcCCtx->blockState.matchState.hashLog3;
   1944        size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
   1945
   1946        ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable,
   1947               srcCCtx->blockState.matchState.hashTable,
   1948               hSize * sizeof(U32));
   1949        ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable,
   1950               srcCCtx->blockState.matchState.chainTable,
   1951               chainSize * sizeof(U32));
   1952        ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3,
   1953               srcCCtx->blockState.matchState.hashTable3,
   1954               h3Size * sizeof(U32));
   1955    }
   1956
   1957    ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);
   1958
   1959    /* copy dictionary offsets */
   1960    {
   1961        const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
   1962        ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
   1963        dstMatchState->window       = srcMatchState->window;
   1964        dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
   1965        dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
   1966    }
   1967    dstCCtx->dictID = srcCCtx->dictID;
   1968    dstCCtx->dictContentSize = srcCCtx->dictContentSize;
   1969
   1970    /* copy block state */
   1971    ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
   1972
   1973    return 0;
   1974}
   1975
   1976/*! ZSTD_copyCCtx() :
   1977 *  Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
   1978 *  Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
   1979 *  pledgedSrcSize==0 means "unknown".
   1980*   @return : 0, or an error code */
   1981size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
   1982{
   1983    ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
   1984    ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy;
   1985    ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
   1986    if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
   1987    fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
   1988
   1989    return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,
   1990                                fParams, pledgedSrcSize,
   1991                                zbuff);
   1992}
   1993
   1994
   1995#define ZSTD_ROWSIZE 16
   1996/*! ZSTD_reduceTable() :
   1997 *  reduce table indexes by `reducerValue`, or squash to zero.
   1998 *  PreserveMark preserves "unsorted mark" for btlazy2 strategy.
   1999 *  It must be set to a clear 0/1 value, to remove branch during inlining.
   2000 *  Presume table size is a multiple of ZSTD_ROWSIZE
   2001 *  to help auto-vectorization */
   2002FORCE_INLINE_TEMPLATE void
   2003ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)
   2004{
   2005    int const nbRows = (int)size / ZSTD_ROWSIZE;
   2006    int cellNb = 0;
   2007    int rowNb;
   2008    assert((size & (ZSTD_ROWSIZE-1)) == 0);  /* multiple of ZSTD_ROWSIZE */
   2009    assert(size < (1U<<31));   /* can be casted to int */
   2010
   2011
   2012    for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
   2013        int column;
   2014        for (column=0; column<ZSTD_ROWSIZE; column++) {
   2015            if (preserveMark) {
   2016                U32 const adder = (table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) ? reducerValue : 0;
   2017                table[cellNb] += adder;
   2018            }
   2019            if (table[cellNb] < reducerValue) table[cellNb] = 0;
   2020            else table[cellNb] -= reducerValue;
   2021            cellNb++;
   2022    }   }
   2023}
   2024
   2025static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
   2026{
   2027    ZSTD_reduceTable_internal(table, size, reducerValue, 0);
   2028}
   2029
   2030static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
   2031{
   2032    ZSTD_reduceTable_internal(table, size, reducerValue, 1);
   2033}
   2034
   2035/*! ZSTD_reduceIndex() :
   2036*   rescale all indexes to avoid future overflow (indexes are U32) */
   2037static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
   2038{
   2039    {   U32 const hSize = (U32)1 << params->cParams.hashLog;
   2040        ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
   2041    }
   2042
   2043    if (params->cParams.strategy != ZSTD_fast) {
   2044        U32 const chainSize = (U32)1 << params->cParams.chainLog;
   2045        if (params->cParams.strategy == ZSTD_btlazy2)
   2046            ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
   2047        else
   2048            ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
   2049    }
   2050
   2051    if (ms->hashLog3) {
   2052        U32 const h3Size = (U32)1 << ms->hashLog3;
   2053        ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);
   2054    }
   2055}
   2056
   2057
   2058/*-*******************************************************
   2059*  Block entropic compression
   2060*********************************************************/
   2061
   2062/* See doc/zstd_compression_format.md for detailed format description */
   2063
   2064void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
   2065{
   2066    const seqDef* const sequences = seqStorePtr->sequencesStart;
   2067    BYTE* const llCodeTable = seqStorePtr->llCode;
   2068    BYTE* const ofCodeTable = seqStorePtr->ofCode;
   2069    BYTE* const mlCodeTable = seqStorePtr->mlCode;
   2070    U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
   2071    U32 u;
   2072    assert(nbSeq <= seqStorePtr->maxNbSeq);
   2073    for (u=0; u<nbSeq; u++) {
   2074        U32 const llv = sequences[u].litLength;
   2075        U32 const mlv = sequences[u].matchLength;
   2076        llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
   2077        ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
   2078        mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
   2079    }
   2080    if (seqStorePtr->longLengthID==1)
   2081        llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
   2082    if (seqStorePtr->longLengthID==2)
   2083        mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
   2084}
   2085
   2086/* ZSTD_useTargetCBlockSize():
   2087 * Returns if target compressed block size param is being used.
   2088 * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize.
   2089 * Returns 1 if true, 0 otherwise. */
   2090static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
   2091{
   2092    DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
   2093    return (cctxParams->targetCBlockSize != 0);
   2094}
   2095
   2096/* ZSTD_entropyCompressSequences_internal():
   2097 * actually compresses both literals and sequences */
   2098MEM_STATIC size_t
   2099ZSTD_entropyCompressSequences_internal(seqStore_t* seqStorePtr,
   2100                          const ZSTD_entropyCTables_t* prevEntropy,
   2101                                ZSTD_entropyCTables_t* nextEntropy,
   2102                          const ZSTD_CCtx_params* cctxParams,
   2103                                void* dst, size_t dstCapacity,
   2104                                void* entropyWorkspace, size_t entropyWkspSize,
   2105                          const int bmi2)
   2106{
   2107    const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
   2108    ZSTD_strategy const strategy = cctxParams->cParams.strategy;
   2109    unsigned* count = (unsigned*)entropyWorkspace;
   2110    FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
   2111    FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
   2112    FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
   2113    U32 LLtype, Offtype, MLtype;   /* compressed, raw or rle */
   2114    const seqDef* const sequences = seqStorePtr->sequencesStart;
   2115    const BYTE* const ofCodeTable = seqStorePtr->ofCode;
   2116    const BYTE* const llCodeTable = seqStorePtr->llCode;
   2117    const BYTE* const mlCodeTable = seqStorePtr->mlCode;
   2118    BYTE* const ostart = (BYTE*)dst;
   2119    BYTE* const oend = ostart + dstCapacity;
   2120    BYTE* op = ostart;
   2121    size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
   2122    BYTE* seqHead;
   2123    BYTE* lastNCount = NULL;
   2124
   2125    entropyWorkspace = count + (MaxSeq + 1);
   2126    entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);
   2127
   2128    DEBUGLOG(4, "ZSTD_entropyCompressSequences_internal (nbSeq=%zu)", nbSeq);
   2129    ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
   2130    assert(entropyWkspSize >= HUF_WORKSPACE_SIZE);
   2131
   2132    /* Compress literals */
   2133    {   const BYTE* const literals = seqStorePtr->litStart;
   2134        size_t const litSize = (size_t)(seqStorePtr->lit - literals);
   2135        size_t const cSize = ZSTD_compressLiterals(
   2136                                    &prevEntropy->huf, &nextEntropy->huf,
   2137                                    cctxParams->cParams.strategy,
   2138                                    ZSTD_disableLiteralsCompression(cctxParams),
   2139                                    op, dstCapacity,
   2140                                    literals, litSize,
   2141                                    entropyWorkspace, entropyWkspSize,
   2142                                    bmi2);
   2143        FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
   2144        assert(cSize <= dstCapacity);
   2145        op += cSize;
   2146    }
   2147
   2148    /* Sequences Header */
   2149    RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
   2150                    dstSize_tooSmall, "Can't fit seq hdr in output buf!");
   2151    if (nbSeq < 128) {
   2152        *op++ = (BYTE)nbSeq;
   2153    } else if (nbSeq < LONGNBSEQ) {
   2154        op[0] = (BYTE)((nbSeq>>8) + 0x80);
   2155        op[1] = (BYTE)nbSeq;
   2156        op+=2;
   2157    } else {
   2158        op[0]=0xFF;
   2159        MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ));
   2160        op+=3;
   2161    }
   2162    assert(op <= oend);
   2163    if (nbSeq==0) {
   2164        /* Copy the old tables over as if we repeated them */
   2165        ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
   2166        return (size_t)(op - ostart);
   2167    }
   2168
   2169    /* seqHead : flags for FSE encoding type */
   2170    seqHead = op++;
   2171    assert(op <= oend);
   2172
   2173    /* convert length/distances into codes */
   2174    ZSTD_seqToCodes(seqStorePtr);
   2175    /* build CTable for Literal Lengths */
   2176    {   unsigned max = MaxLL;
   2177        size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */
   2178        DEBUGLOG(5, "Building LL table");
   2179        nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
   2180        LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
   2181                                        count, max, mostFrequent, nbSeq,
   2182                                        LLFSELog, prevEntropy->fse.litlengthCTable,
   2183                                        LL_defaultNorm, LL_defaultNormLog,
   2184                                        ZSTD_defaultAllowed, strategy);
   2185        assert(set_basic < set_compressed && set_rle < set_compressed);
   2186        assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
   2187        {   size_t const countSize = ZSTD_buildCTable(
   2188                op, (size_t)(oend - op),
   2189                CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
   2190                count, max, llCodeTable, nbSeq,
   2191                LL_defaultNorm, LL_defaultNormLog, MaxLL,
   2192                prevEntropy->fse.litlengthCTable,
   2193                sizeof(prevEntropy->fse.litlengthCTable),
   2194                entropyWorkspace, entropyWkspSize);
   2195            FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
   2196            if (LLtype == set_compressed)
   2197                lastNCount = op;
   2198            op += countSize;
   2199            assert(op <= oend);
   2200    }   }
   2201    /* build CTable for Offsets */
   2202    {   unsigned max = MaxOff;
   2203        size_t const mostFrequent = HIST_countFast_wksp(
   2204            count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);  /* can't fail */
   2205        /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
   2206        ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
   2207        DEBUGLOG(5, "Building OF table");
   2208        nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode;
   2209        Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode,
   2210                                        count, max, mostFrequent, nbSeq,
   2211                                        OffFSELog, prevEntropy->fse.offcodeCTable,
   2212                                        OF_defaultNorm, OF_defaultNormLog,
   2213                                        defaultPolicy, strategy);
   2214        assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
   2215        {   size_t const countSize = ZSTD_buildCTable(
   2216                op, (size_t)(oend - op),
   2217                CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
   2218                count, max, ofCodeTable, nbSeq,
   2219                OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
   2220                prevEntropy->fse.offcodeCTable,
   2221                sizeof(prevEntropy->fse.offcodeCTable),
   2222                entropyWorkspace, entropyWkspSize);
   2223            FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
   2224            if (Offtype == set_compressed)
   2225                lastNCount = op;
   2226            op += countSize;
   2227            assert(op <= oend);
   2228    }   }
   2229    /* build CTable for MatchLengths */
   2230    {   unsigned max = MaxML;
   2231        size_t const mostFrequent = HIST_countFast_wksp(
   2232            count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */
   2233        DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
   2234        nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
   2235        MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
   2236                                        count, max, mostFrequent, nbSeq,
   2237                                        MLFSELog, prevEntropy->fse.matchlengthCTable,
   2238                                        ML_defaultNorm, ML_defaultNormLog,
   2239                                        ZSTD_defaultAllowed, strategy);
   2240        assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
   2241        {   size_t const countSize = ZSTD_buildCTable(
   2242                op, (size_t)(oend - op),
   2243                CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
   2244                count, max, mlCodeTable, nbSeq,
   2245                ML_defaultNorm, ML_defaultNormLog, MaxML,
   2246                prevEntropy->fse.matchlengthCTable,
   2247                sizeof(prevEntropy->fse.matchlengthCTable),
   2248                entropyWorkspace, entropyWkspSize);
   2249            FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
   2250            if (MLtype == set_compressed)
   2251                lastNCount = op;
   2252            op += countSize;
   2253            assert(op <= oend);
   2254    }   }
   2255
   2256    *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
   2257
   2258    {   size_t const bitstreamSize = ZSTD_encodeSequences(
   2259                                        op, (size_t)(oend - op),
   2260                                        CTable_MatchLength, mlCodeTable,
   2261                                        CTable_OffsetBits, ofCodeTable,
   2262                                        CTable_LitLength, llCodeTable,
   2263                                        sequences, nbSeq,
   2264                                        longOffsets, bmi2);
   2265        FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
   2266        op += bitstreamSize;
   2267        assert(op <= oend);
   2268        /* zstd versions <= 1.3.4 mistakenly report corruption when
   2269         * FSE_readNCount() receives a buffer < 4 bytes.
   2270         * Fixed by https://github.com/facebook/zstd/pull/1146.
   2271         * This can happen when the last set_compressed table present is 2
   2272         * bytes and the bitstream is only one byte.
   2273         * In this exceedingly rare case, we will simply emit an uncompressed
   2274         * block, since it isn't worth optimizing.
   2275         */
   2276        if (lastNCount && (op - lastNCount) < 4) {
   2277            /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
   2278            assert(op - lastNCount == 3);
   2279            DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
   2280                        "emitting an uncompressed block.");
   2281            return 0;
   2282        }
   2283    }
   2284
   2285    DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
   2286    return (size_t)(op - ostart);
   2287}
   2288
   2289MEM_STATIC size_t
   2290ZSTD_entropyCompressSequences(seqStore_t* seqStorePtr,
   2291                       const ZSTD_entropyCTables_t* prevEntropy,
   2292                             ZSTD_entropyCTables_t* nextEntropy,
   2293                       const ZSTD_CCtx_params* cctxParams,
   2294                             void* dst, size_t dstCapacity,
   2295                             size_t srcSize,
   2296                             void* entropyWorkspace, size_t entropyWkspSize,
   2297                             int bmi2)
   2298{
   2299    size_t const cSize = ZSTD_entropyCompressSequences_internal(
   2300                            seqStorePtr, prevEntropy, nextEntropy, cctxParams,
   2301                            dst, dstCapacity,
   2302                            entropyWorkspace, entropyWkspSize, bmi2);
   2303    if (cSize == 0) return 0;
   2304    /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
   2305     * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
   2306     */
   2307    if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
   2308        return 0;  /* block not compressed */
   2309    FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSequences_internal failed");
   2310
   2311    /* Check compressibility */
   2312    {   size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
   2313        if (cSize >= maxCSize) return 0;  /* block not compressed */
   2314    }
   2315    DEBUGLOG(4, "ZSTD_entropyCompressSequences() cSize: %zu\n", cSize);
   2316    return cSize;
   2317}
   2318
   2319/* ZSTD_selectBlockCompressor() :
   2320 * Not static, but internal use only (used by long distance matcher)
   2321 * assumption : strat is a valid strategy */
   2322ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
   2323{
   2324    static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
   2325        { ZSTD_compressBlock_fast  /* default for 0 */,
   2326          ZSTD_compressBlock_fast,
   2327          ZSTD_compressBlock_doubleFast,
   2328          ZSTD_compressBlock_greedy,
   2329          ZSTD_compressBlock_lazy,
   2330          ZSTD_compressBlock_lazy2,
   2331          ZSTD_compressBlock_btlazy2,
   2332          ZSTD_compressBlock_btopt,
   2333          ZSTD_compressBlock_btultra,
   2334          ZSTD_compressBlock_btultra2 },
   2335        { ZSTD_compressBlock_fast_extDict  /* default for 0 */,
   2336          ZSTD_compressBlock_fast_extDict,
   2337          ZSTD_compressBlock_doubleFast_extDict,
   2338          ZSTD_compressBlock_greedy_extDict,
   2339          ZSTD_compressBlock_lazy_extDict,
   2340          ZSTD_compressBlock_lazy2_extDict,
   2341          ZSTD_compressBlock_btlazy2_extDict,
   2342          ZSTD_compressBlock_btopt_extDict,
   2343          ZSTD_compressBlock_btultra_extDict,
   2344          ZSTD_compressBlock_btultra_extDict },
   2345        { ZSTD_compressBlock_fast_dictMatchState  /* default for 0 */,
   2346          ZSTD_compressBlock_fast_dictMatchState,
   2347          ZSTD_compressBlock_doubleFast_dictMatchState,
   2348          ZSTD_compressBlock_greedy_dictMatchState,
   2349          ZSTD_compressBlock_lazy_dictMatchState,
   2350          ZSTD_compressBlock_lazy2_dictMatchState,
   2351          ZSTD_compressBlock_btlazy2_dictMatchState,
   2352          ZSTD_compressBlock_btopt_dictMatchState,
   2353          ZSTD_compressBlock_btultra_dictMatchState,
   2354          ZSTD_compressBlock_btultra_dictMatchState },
   2355        { NULL  /* default for 0 */,
   2356          NULL,
   2357          NULL,
   2358          ZSTD_compressBlock_greedy_dedicatedDictSearch,
   2359          ZSTD_compressBlock_lazy_dedicatedDictSearch,
   2360          ZSTD_compressBlock_lazy2_dedicatedDictSearch,
   2361          NULL,
   2362          NULL,
   2363          NULL,
   2364          NULL }
   2365    };
   2366    ZSTD_blockCompressor selectedCompressor;
   2367    ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
   2368
   2369    assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
   2370    selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
   2371    assert(selectedCompressor != NULL);
   2372    return selectedCompressor;
   2373}
   2374
   2375static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
   2376                                   const BYTE* anchor, size_t lastLLSize)
   2377{
   2378    ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize);
   2379    seqStorePtr->lit += lastLLSize;
   2380}
   2381
   2382void ZSTD_resetSeqStore(seqStore_t* ssPtr)
   2383{
   2384    ssPtr->lit = ssPtr->litStart;
   2385    ssPtr->sequences = ssPtr->sequencesStart;
   2386    ssPtr->longLengthID = 0;
   2387}
   2388
   2389typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
   2390
   2391static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
   2392{
   2393    ZSTD_matchState_t* const ms = &zc->blockState.matchState;
   2394    DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
   2395    assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
   2396    /* Assert that we have correctly flushed the ctx params into the ms's copy */
   2397    ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
   2398    if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
   2399        if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) {
   2400            ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize);
   2401        } else {
   2402            ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
   2403        }
   2404        return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
   2405    }
   2406    ZSTD_resetSeqStore(&(zc->seqStore));
   2407    /* required for optimal parser to read stats from dictionary */
   2408    ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
   2409    /* tell the optimal parser how we expect to compress literals */
   2410    ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
   2411    /* a gap between an attached dict and the current window is not safe,
   2412     * they must remain adjacent,
   2413     * and when that stops being the case, the dict must be unset */
   2414    assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);
   2415
   2416    /* limited update after a very long match */
   2417    {   const BYTE* const base = ms->window.base;
   2418        const BYTE* const istart = (const BYTE*)src;
   2419        const U32 curr = (U32)(istart-base);
   2420        if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1));   /* ensure no overflow */
   2421        if (curr > ms->nextToUpdate + 384)
   2422            ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
   2423    }
   2424
   2425    /* select and store sequences */
   2426    {   ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
   2427        size_t lastLLSize;
   2428        {   int i;
   2429            for (i = 0; i < ZSTD_REP_NUM; ++i)
   2430                zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];
   2431        }
   2432        if (zc->externSeqStore.pos < zc->externSeqStore.size) {
   2433            assert(!zc->appliedParams.ldmParams.enableLdm);
   2434            /* Updates ldmSeqStore.pos */
   2435            lastLLSize =
   2436                ZSTD_ldm_blockCompress(&zc->externSeqStore,
   2437                                       ms, &zc->seqStore,
   2438                                       zc->blockState.nextCBlock->rep,
   2439                                       src, srcSize);
   2440            assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
   2441        } else if (zc->appliedParams.ldmParams.enableLdm) {
   2442            rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
   2443
   2444            ldmSeqStore.seq = zc->ldmSequences;
   2445            ldmSeqStore.capacity = zc->maxNbLdmSequences;
   2446            /* Updates ldmSeqStore.size */
   2447            FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
   2448                                               &zc->appliedParams.ldmParams,
   2449                                               src, srcSize), "");
   2450            /* Updates ldmSeqStore.pos */
   2451            lastLLSize =
   2452                ZSTD_ldm_blockCompress(&ldmSeqStore,
   2453                                       ms, &zc->seqStore,
   2454                                       zc->blockState.nextCBlock->rep,
   2455                                       src, srcSize);
   2456            assert(ldmSeqStore.pos == ldmSeqStore.size);
   2457        } else {   /* not long range mode */
   2458            ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
   2459            ms->ldmSeqStore = NULL;
   2460            lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
   2461        }
   2462        {   const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
   2463            ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
   2464    }   }
   2465    return ZSTDbss_compress;
   2466}
   2467
   2468static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
   2469{
   2470    const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
   2471    const seqDef* seqStoreSeqs = seqStore->sequencesStart;
   2472    size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs;
   2473    size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart);
   2474    size_t literalsRead = 0;
   2475    size_t lastLLSize;
   2476
   2477    ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
   2478    size_t i;
   2479    repcodes_t updatedRepcodes;
   2480
   2481    assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
   2482    /* Ensure we have enough space for last literals "sequence" */
   2483    assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
   2484    ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
   2485    for (i = 0; i < seqStoreSeqSize; ++i) {
   2486        U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM;
   2487        outSeqs[i].litLength = seqStoreSeqs[i].litLength;
   2488        outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH;
   2489        outSeqs[i].rep = 0;
   2490
   2491        if (i == seqStore->longLengthPos) {
   2492            if (seqStore->longLengthID == 1) {
   2493                outSeqs[i].litLength += 0x10000;
   2494            } else if (seqStore->longLengthID == 2) {
   2495                outSeqs[i].matchLength += 0x10000;
   2496            }
   2497        }
   2498
   2499        if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) {
   2500            /* Derive the correct offset corresponding to a repcode */
   2501            outSeqs[i].rep = seqStoreSeqs[i].offset;
   2502            if (outSeqs[i].litLength != 0) {
   2503                rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
   2504            } else {
   2505                if (outSeqs[i].rep == 3) {
   2506                    rawOffset = updatedRepcodes.rep[0] - 1;
   2507                } else {
   2508                    rawOffset = updatedRepcodes.rep[outSeqs[i].rep];
   2509                }
   2510            }
   2511        }
   2512        outSeqs[i].offset = rawOffset;
   2513        /* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
   2514           so we provide seqStoreSeqs[i].offset - 1 */
   2515        updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep,
   2516                                         seqStoreSeqs[i].offset - 1,
   2517                                         seqStoreSeqs[i].litLength == 0);
   2518        literalsRead += outSeqs[i].litLength;
   2519    }
   2520    /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
   2521     * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker
   2522     * for the block boundary, according to the API.
   2523     */
   2524    assert(seqStoreLiteralsSize >= literalsRead);
   2525    lastLLSize = seqStoreLiteralsSize - literalsRead;
   2526    outSeqs[i].litLength = (U32)lastLLSize;
   2527    outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0;
   2528    seqStoreSeqSize++;
   2529    zc->seqCollector.seqIndex += seqStoreSeqSize;
   2530}
   2531
   2532size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
   2533                              size_t outSeqsSize, const void* src, size_t srcSize)
   2534{
   2535    const size_t dstCapacity = ZSTD_compressBound(srcSize);
   2536    void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
   2537    SeqCollector seqCollector;
   2538
   2539    RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
   2540
   2541    seqCollector.collectSequences = 1;
   2542    seqCollector.seqStart = outSeqs;
   2543    seqCollector.seqIndex = 0;
   2544    seqCollector.maxSequences = outSeqsSize;
   2545    zc->seqCollector = seqCollector;
   2546
   2547    ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
   2548    ZSTD_customFree(dst, ZSTD_defaultCMem);
   2549    return zc->seqCollector.seqIndex;
   2550}
   2551
   2552size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) {
   2553    size_t in = 0;
   2554    size_t out = 0;
   2555    for (; in < seqsSize; ++in) {
   2556        if (sequences[in].offset == 0 && sequences[in].matchLength == 0) {
   2557            if (in != seqsSize - 1) {
   2558                sequences[in+1].litLength += sequences[in].litLength;
   2559            }
   2560        } else {
   2561            sequences[out] = sequences[in];
   2562            ++out;
   2563        }
   2564    }
   2565    return out;
   2566}
   2567
   2568/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */
   2569static int ZSTD_isRLE(const BYTE* src, size_t length) {
   2570    const BYTE* ip = src;
   2571    const BYTE value = ip[0];
   2572    const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL);
   2573    const size_t unrollSize = sizeof(size_t) * 4;
   2574    const size_t unrollMask = unrollSize - 1;
   2575    const size_t prefixLength = length & unrollMask;
   2576    size_t i;
   2577    size_t u;
   2578    if (length == 1) return 1;
   2579    /* Check if prefix is RLE first before using unrolled loop */
   2580    if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {
   2581        return 0;
   2582    }
   2583    for (i = prefixLength; i != length; i += unrollSize) {
   2584        for (u = 0; u < unrollSize; u += sizeof(size_t)) {
   2585            if (MEM_readST(ip + i + u) != valueST) {
   2586                return 0;
   2587            }
   2588        }
   2589    }
   2590    return 1;
   2591}
   2592
   2593/* Returns true if the given block may be RLE.
   2594 * This is just a heuristic based on the compressibility.
   2595 * It may return both false positives and false negatives.
   2596 */
   2597static int ZSTD_maybeRLE(seqStore_t const* seqStore)
   2598{
   2599    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);
   2600    size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart);
   2601
   2602    return nbSeqs < 4 && nbLits < 10;
   2603}
   2604
   2605static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc)
   2606{
   2607    ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
   2608    zc->blockState.prevCBlock = zc->blockState.nextCBlock;
   2609    zc->blockState.nextCBlock = tmp;
   2610}
   2611
   2612static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
   2613                                        void* dst, size_t dstCapacity,
   2614                                        const void* src, size_t srcSize, U32 frame)
   2615{
   2616    /* This the upper bound for the length of an rle block.
   2617     * This isn't the actual upper bound. Finding the real threshold
   2618     * needs further investigation.
   2619     */
   2620    const U32 rleMaxLength = 25;
   2621    size_t cSize;
   2622    const BYTE* ip = (const BYTE*)src;
   2623    BYTE* op = (BYTE*)dst;
   2624    DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
   2625                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
   2626                (unsigned)zc->blockState.matchState.nextToUpdate);
   2627
   2628    {   const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
   2629        FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
   2630        if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
   2631    }
   2632
   2633    if (zc->seqCollector.collectSequences) {
   2634        ZSTD_copyBlockSequences(zc);
   2635        ZSTD_confirmRepcodesAndEntropyTables(zc);
   2636        return 0;
   2637    }
   2638
   2639    /* encode sequences and literals */
   2640    cSize = ZSTD_entropyCompressSequences(&zc->seqStore,
   2641            &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
   2642            &zc->appliedParams,
   2643            dst, dstCapacity,
   2644            srcSize,
   2645            zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
   2646            zc->bmi2);
   2647
   2648    if (zc->seqCollector.collectSequences) {
   2649        ZSTD_copyBlockSequences(zc);
   2650        return 0;
   2651    }
   2652
   2653
   2654    if (frame &&
   2655        /* We don't want to emit our first block as a RLE even if it qualifies because
   2656         * doing so will cause the decoder (cli only) to throw a "should consume all input error."
   2657         * This is only an issue for zstd <= v1.4.3
   2658         */
   2659        !zc->isFirstBlock &&
   2660        cSize < rleMaxLength &&
   2661        ZSTD_isRLE(ip, srcSize))
   2662    {
   2663        cSize = 1;
   2664        op[0] = ip[0];
   2665    }
   2666
   2667out:
   2668    if (!ZSTD_isError(cSize) && cSize > 1) {
   2669        ZSTD_confirmRepcodesAndEntropyTables(zc);
   2670    }
   2671    /* We check that dictionaries have offset codes available for the first
   2672     * block. After the first block, the offcode table might not have large
   2673     * enough codes to represent the offsets in the data.
   2674     */
   2675    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
   2676        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
   2677
   2678    return cSize;
   2679}
   2680
   2681static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
   2682                               void* dst, size_t dstCapacity,
   2683                               const void* src, size_t srcSize,
   2684                               const size_t bss, U32 lastBlock)
   2685{
   2686    DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()");
   2687    if (bss == ZSTDbss_compress) {
   2688        if (/* We don't want to emit our first block as a RLE even if it qualifies because
   2689            * doing so will cause the decoder (cli only) to throw a "should consume all input error."
   2690            * This is only an issue for zstd <= v1.4.3
   2691            */
   2692            !zc->isFirstBlock &&
   2693            ZSTD_maybeRLE(&zc->seqStore) &&
   2694            ZSTD_isRLE((BYTE const*)src, srcSize))
   2695        {
   2696            return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock);
   2697        }
   2698        /* Attempt superblock compression.
   2699         *
   2700         * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the
   2701         * standard ZSTD_compressBound(). This is a problem, because even if we have
   2702         * space now, taking an extra byte now could cause us to run out of space later
   2703         * and violate ZSTD_compressBound().
   2704         *
   2705         * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize.
   2706         *
   2707         * In order to respect ZSTD_compressBound() we must attempt to emit a raw
   2708         * uncompressed block in these cases:
   2709         *   * cSize == 0: Return code for an uncompressed block.
   2710         *   * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize).
   2711         *     ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of
   2712         *     output space.
   2713         *   * cSize >= blockBound(srcSize): We have expanded the block too much so
   2714         *     emit an uncompressed block.
   2715         */
   2716        {
   2717            size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);
   2718            if (cSize != ERROR(dstSize_tooSmall)) {
   2719                size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
   2720                FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed");
   2721                if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {
   2722                    ZSTD_confirmRepcodesAndEntropyTables(zc);
   2723                    return cSize;
   2724                }
   2725            }
   2726        }
   2727    }
   2728
   2729    DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()");
   2730    /* Superblock compression failed, attempt to emit a single no compress block.
   2731     * The decoder will be able to stream this block since it is uncompressed.
   2732     */
   2733    return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
   2734}
   2735
   2736static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,
   2737                               void* dst, size_t dstCapacity,
   2738                               const void* src, size_t srcSize,
   2739                               U32 lastBlock)
   2740{
   2741    size_t cSize = 0;
   2742    const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
   2743    DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)",
   2744                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);
   2745    FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
   2746
   2747    cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock);
   2748    FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed");
   2749
   2750    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
   2751        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
   2752
   2753    return cSize;
   2754}
   2755
   2756static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
   2757                                         ZSTD_cwksp* ws,
   2758                                         ZSTD_CCtx_params const* params,
   2759                                         void const* ip,
   2760                                         void const* iend)
   2761{
   2762    if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
   2763        U32 const maxDist = (U32)1 << params->cParams.windowLog;
   2764        U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
   2765        U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
   2766        ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
   2767        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
   2768        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
   2769        ZSTD_cwksp_mark_tables_dirty(ws);
   2770        ZSTD_reduceIndex(ms, params, correction);
   2771        ZSTD_cwksp_mark_tables_clean(ws);
   2772        if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
   2773        else ms->nextToUpdate -= correction;
   2774        /* invalidate dictionaries on overflow correction */
   2775        ms->loadedDictEnd = 0;
   2776        ms->dictMatchState = NULL;
   2777    }
   2778}
   2779
   2780/*! ZSTD_compress_frameChunk() :
   2781*   Compress a chunk of data into one or multiple blocks.
   2782*   All blocks will be terminated, all input will be consumed.
   2783*   Function will issue an error if there is not enough `dstCapacity` to hold the compressed content.
   2784*   Frame is supposed already started (header already produced)
   2785*   @return : compressed size, or an error code
   2786*/
   2787static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
   2788                                     void* dst, size_t dstCapacity,
   2789                               const void* src, size_t srcSize,
   2790                                     U32 lastFrameChunk)
   2791{
   2792    size_t blockSize = cctx->blockSize;
   2793    size_t remaining = srcSize;
   2794    const BYTE* ip = (const BYTE*)src;
   2795    BYTE* const ostart = (BYTE*)dst;
   2796    BYTE* op = ostart;
   2797    U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
   2798
   2799    assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
   2800
   2801    DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
   2802    if (cctx->appliedParams.fParams.checksumFlag && srcSize)
   2803        xxh64_update(&cctx->xxhState, src, srcSize);
   2804
   2805    while (remaining) {
   2806        ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
   2807        U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
   2808
   2809        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
   2810                        dstSize_tooSmall,
   2811                        "not enough space to store compressed block");
   2812        if (remaining < blockSize) blockSize = remaining;
   2813
   2814        ZSTD_overflowCorrectIfNeeded(
   2815            ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);
   2816        ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
   2817
   2818        /* Ensure hash/chain table insertion resumes no sooner than lowlimit */
   2819        if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
   2820
   2821        {   size_t cSize;
   2822            if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) {
   2823                cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);
   2824                FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed");
   2825                assert(cSize > 0);
   2826                assert(cSize <= blockSize + ZSTD_blockHeaderSize);
   2827            } else {
   2828                cSize = ZSTD_compressBlock_internal(cctx,
   2829                                        op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
   2830                                        ip, blockSize, 1 /* frame */);
   2831                FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed");
   2832
   2833                if (cSize == 0) {  /* block is not compressible */
   2834                    cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
   2835                    FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
   2836                } else {
   2837                    U32 const cBlockHeader = cSize == 1 ?
   2838                        lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
   2839                        lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
   2840                    MEM_writeLE24(op, cBlockHeader);
   2841                    cSize += ZSTD_blockHeaderSize;
   2842                }
   2843            }
   2844
   2845
   2846            ip += blockSize;
   2847            assert(remaining >= blockSize);
   2848            remaining -= blockSize;
   2849            op += cSize;
   2850            assert(dstCapacity >= cSize);
   2851            dstCapacity -= cSize;
   2852            cctx->isFirstBlock = 0;
   2853            DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
   2854                        (unsigned)cSize);
   2855    }   }
   2856
   2857    if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
   2858    return (size_t)(op-ostart);
   2859}
   2860
   2861
   2862static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
   2863                                    const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID)
   2864{   BYTE* const op = (BYTE*)dst;
   2865    U32   const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536);   /* 0-3 */
   2866    U32   const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength;   /* 0-3 */
   2867    U32   const checksumFlag = params->fParams.checksumFlag>0;
   2868    U32   const windowSize = (U32)1 << params->cParams.windowLog;
   2869    U32   const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
   2870    BYTE  const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
   2871    U32   const fcsCode = params->fParams.contentSizeFlag ?
   2872                     (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0;  /* 0-3 */
   2873    BYTE  const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
   2874    size_t pos=0;
   2875
   2876    assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
   2877    RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall,
   2878                    "dst buf is too small to fit worst-case frame header size.");
   2879    DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
   2880                !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
   2881    if (params->format == ZSTD_f_zstd1) {
   2882        MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
   2883        pos = 4;
   2884    }
   2885    op[pos++] = frameHeaderDescriptionByte;
   2886    if (!singleSegment) op[pos++] = windowLogByte;
   2887    switch(dictIDSizeCode)
   2888    {
   2889        default:
   2890            assert(0); /* impossible */
   2891            ZSTD_FALLTHROUGH;
   2892        case 0 : break;
   2893        case 1 : op[pos] = (BYTE)(dictID); pos++; break;
   2894        case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;
   2895        case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break;
   2896    }
   2897    switch(fcsCode)
   2898    {
   2899        default:
   2900            assert(0); /* impossible */
   2901            ZSTD_FALLTHROUGH;
   2902        case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;
   2903        case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;
   2904        case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;
   2905        case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break;
   2906    }
   2907    return pos;
   2908}
   2909
   2910/* ZSTD_writeSkippableFrame_advanced() :
   2911 * Writes out a skippable frame with the specified magic number variant (16 are supported),
   2912 * from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data.
   2913 *
   2914 * Returns the total number of bytes written, or a ZSTD error code.
   2915 */
   2916size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
   2917                                const void* src, size_t srcSize, unsigned magicVariant) {
   2918    BYTE* op = (BYTE*)dst;
   2919    RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */,
   2920                    dstSize_tooSmall, "Not enough room for skippable frame");
   2921    RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, "Src size too large for skippable frame");
   2922    RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, "Skippable frame magic number variant not supported");
   2923
   2924    MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant));
   2925    MEM_writeLE32(op+4, (U32)srcSize);
   2926    ZSTD_memcpy(op+8, src, srcSize);
   2927    return srcSize + ZSTD_SKIPPABLEHEADERSIZE;
   2928}
   2929
   2930/* ZSTD_writeLastEmptyBlock() :
   2931 * output an empty Block with end-of-frame mark to complete a frame
   2932 * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
   2933 *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
   2934 */
   2935size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
   2936{
   2937    RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,
   2938                    "dst buf is too small to write frame trailer empty block.");
   2939    {   U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1);  /* 0 size */
   2940        MEM_writeLE24(dst, cBlockHeader24);
   2941        return ZSTD_blockHeaderSize;
   2942    }
   2943}
   2944
   2945size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
   2946{
   2947    RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
   2948                    "wrong cctx stage");
   2949    RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
   2950                    parameter_unsupported,
   2951                    "incompatible with ldm");
   2952    cctx->externSeqStore.seq = seq;
   2953    cctx->externSeqStore.size = nbSeq;
   2954    cctx->externSeqStore.capacity = nbSeq;
   2955    cctx->externSeqStore.pos = 0;
   2956    cctx->externSeqStore.posInSequence = 0;
   2957    return 0;
   2958}
   2959
   2960
   2961static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
   2962                              void* dst, size_t dstCapacity,
   2963                        const void* src, size_t srcSize,
   2964                               U32 frame, U32 lastFrameChunk)
   2965{
   2966    ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
   2967    size_t fhSize = 0;
   2968
   2969    DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
   2970                cctx->stage, (unsigned)srcSize);
   2971    RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
   2972                    "missing init (ZSTD_compressBegin)");
   2973
   2974    if (frame && (cctx->stage==ZSTDcs_init)) {
   2975        fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,
   2976                                       cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
   2977        FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
   2978        assert(fhSize <= dstCapacity);
   2979        dstCapacity -= fhSize;
   2980        dst = (char*)dst + fhSize;
   2981        cctx->stage = ZSTDcs_ongoing;
   2982    }
   2983
   2984    if (!srcSize) return fhSize;  /* do not generate an empty block if no input */
   2985
   2986    if (!ZSTD_window_update(&ms->window, src, srcSize)) {
   2987        ms->nextToUpdate = ms->window.dictLimit;
   2988    }
   2989    if (cctx->appliedParams.ldmParams.enableLdm) {
   2990        ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
   2991    }
   2992
   2993    if (!frame) {
   2994        /* overflow check and correction for block mode */
   2995        ZSTD_overflowCorrectIfNeeded(
   2996            ms, &cctx->workspace, &cctx->appliedParams,
   2997            src, (BYTE const*)src + srcSize);
   2998    }
   2999
   3000    DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
   3001    {   size_t const cSize = frame ?
   3002                             ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
   3003                             ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */);
   3004        FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed");
   3005        cctx->consumedSrcSize += srcSize;
   3006        cctx->producedCSize += (cSize + fhSize);
   3007        assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
   3008        if (cctx->pledgedSrcSizePlusOne != 0) {  /* control src size */
   3009            ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
   3010            RETURN_ERROR_IF(
   3011                cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
   3012                srcSize_wrong,
   3013                "error : pledgedSrcSize = %u, while realSrcSize >= %u",
   3014                (unsigned)cctx->pledgedSrcSizePlusOne-1,
   3015                (unsigned)cctx->consumedSrcSize);
   3016        }
   3017        return cSize + fhSize;
   3018    }
   3019}
   3020
   3021size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
   3022                              void* dst, size_t dstCapacity,
   3023                        const void* src, size_t srcSize)
   3024{
   3025    DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (unsigned)srcSize);
   3026    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);
   3027}
   3028
   3029
   3030size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
   3031{
   3032    ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;
   3033    assert(!ZSTD_checkCParams(cParams));
   3034    return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
   3035}
   3036
   3037size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
   3038{
   3039    DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize);
   3040    { size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
   3041      RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); }
   3042
   3043    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
   3044}
   3045
   3046/*! ZSTD_loadDictionaryContent() :
   3047 *  @return : 0, or an error code
   3048 */
   3049static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
   3050                                         ldmState_t* ls,
   3051                                         ZSTD_cwksp* ws,
   3052                                         ZSTD_CCtx_params const* params,
   3053                                         const void* src, size_t srcSize,
   3054                                         ZSTD_dictTableLoadMethod_e dtlm)
   3055{
   3056    const BYTE* ip = (const BYTE*) src;
   3057    const BYTE* const iend = ip + srcSize;
   3058
   3059    ZSTD_window_update(&ms->window, src, srcSize);
   3060    ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
   3061
   3062    if (params->ldmParams.enableLdm && ls != NULL) {
   3063        ZSTD_window_update(&ls->window, src, srcSize);
   3064        ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);
   3065    }
   3066
   3067    /* Assert that we the ms params match the params we're being given */
   3068    ZSTD_assertEqualCParams(params->cParams, ms->cParams);
   3069
   3070    if (srcSize <= HASH_READ_SIZE) return 0;
   3071
   3072    while (iend - ip > HASH_READ_SIZE) {
   3073        size_t const remaining = (size_t)(iend - ip);
   3074        size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
   3075        const BYTE* const ichunk = ip + chunk;
   3076
   3077        ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
   3078
   3079        if (params->ldmParams.enableLdm && ls != NULL)
   3080            ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, &params->ldmParams);
   3081
   3082        switch(params->cParams.strategy)
   3083        {
   3084        case ZSTD_fast:
   3085            ZSTD_fillHashTable(ms, ichunk, dtlm);
   3086            break;
   3087        case ZSTD_dfast:
   3088            ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
   3089            break;
   3090
   3091        case ZSTD_greedy:
   3092        case ZSTD_lazy:
   3093        case ZSTD_lazy2:
   3094            if (chunk >= HASH_READ_SIZE && ms->dedicatedDictSearch) {
   3095                assert(chunk == remaining); /* must load everything in one go */
   3096                ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, ichunk-HASH_READ_SIZE);
   3097            } else if (chunk >= HASH_READ_SIZE) {
   3098                ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
   3099            }
   3100            break;
   3101
   3102        case ZSTD_btlazy2:   /* we want the dictionary table fully sorted */
   3103        case ZSTD_btopt:
   3104        case ZSTD_btultra:
   3105        case ZSTD_btultra2:
   3106            if (chunk >= HASH_READ_SIZE)
   3107                ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
   3108            break;
   3109
   3110        default:
   3111            assert(0);  /* not possible : not a valid strategy id */
   3112        }
   3113
   3114        ip = ichunk;
   3115    }
   3116
   3117    ms->nextToUpdate = (U32)(iend - ms->window.base);
   3118    return 0;
   3119}
   3120
   3121
   3122/* Dictionaries that assign zero probability to symbols that show up causes problems
   3123 * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check
   3124 * and only dictionaries with 100% valid symbols can be assumed valid.
   3125 */
   3126static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue)
   3127{
   3128    U32 s;
   3129    if (dictMaxSymbolValue < maxSymbolValue) {
   3130        return FSE_repeat_check;
   3131    }
   3132    for (s = 0; s <= maxSymbolValue; ++s) {
   3133        if (normalizedCounter[s] == 0) {
   3134            return FSE_repeat_check;
   3135        }
   3136    }
   3137    return FSE_repeat_valid;
   3138}
   3139
   3140size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
   3141                         const void* const dict, size_t dictSize)
   3142{
   3143    short offcodeNCount[MaxOff+1];
   3144    unsigned offcodeMaxValue = MaxOff;
   3145    const BYTE* dictPtr = (const BYTE*)dict;    /* skip magic num and dict ID */
   3146    const BYTE* const dictEnd = dictPtr + dictSize;
   3147    dictPtr += 8;
   3148    bs->entropy.huf.repeatMode = HUF_repeat_check;
   3149
   3150    {   unsigned maxSymbolValue = 255;
   3151        unsigned hasZeroWeights = 1;
   3152        size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr,
   3153            dictEnd-dictPtr, &hasZeroWeights);
   3154
   3155        /* We only set the loaded table as valid if it contains all non-zero
   3156         * weights. Otherwise, we set it to check */
   3157        if (!hasZeroWeights)
   3158            bs->entropy.huf.repeatMode = HUF_repeat_valid;
   3159
   3160        RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
   3161        RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
   3162        dictPtr += hufHeaderSize;
   3163    }
   3164
   3165    {   unsigned offcodeLog;
   3166        size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
   3167        RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
   3168        RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
   3169        /* fill all offset symbols to avoid garbage at end of table */
   3170        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
   3171                bs->entropy.fse.offcodeCTable,
   3172                offcodeNCount, MaxOff, offcodeLog,
   3173                workspace, HUF_WORKSPACE_SIZE)),
   3174            dictionary_corrupted, "");
   3175        /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
   3176        dictPtr += offcodeHeaderSize;
   3177    }
   3178
   3179    {   short matchlengthNCount[MaxML+1];
   3180        unsigned matchlengthMaxValue = MaxML, matchlengthLog;
   3181        size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
   3182        RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
   3183        RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
   3184        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
   3185                bs->entropy.fse.matchlengthCTable,
   3186                matchlengthNCount, matchlengthMaxValue, matchlengthLog,
   3187                workspace, HUF_WORKSPACE_SIZE)),
   3188            dictionary_corrupted, "");
   3189        bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML);
   3190        dictPtr += matchlengthHeaderSize;
   3191    }
   3192
   3193    {   short litlengthNCount[MaxLL+1];
   3194        unsigned litlengthMaxValue = MaxLL, litlengthLog;
   3195        size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
   3196        RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
   3197        RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
   3198        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
   3199                bs->entropy.fse.litlengthCTable,
   3200                litlengthNCount, litlengthMaxValue, litlengthLog,
   3201                workspace, HUF_WORKSPACE_SIZE)),
   3202            dictionary_corrupted, "");
   3203        bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL);
   3204        dictPtr += litlengthHeaderSize;
   3205    }
   3206
   3207    RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
   3208    bs->rep[0] = MEM_readLE32(dictPtr+0);
   3209    bs->rep[1] = MEM_readLE32(dictPtr+4);
   3210    bs->rep[2] = MEM_readLE32(dictPtr+8);
   3211    dictPtr += 12;
   3212
   3213    {   size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
   3214        U32 offcodeMax = MaxOff;
   3215        if (dictContentSize <= ((U32)-1) - 128 KB) {
   3216            U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
   3217            offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
   3218        }
   3219        /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */
   3220        bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff));
   3221
   3222        /* All repCodes must be <= dictContentSize and != 0 */
   3223        {   U32 u;
   3224            for (u=0; u<3; u++) {
   3225                RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
   3226                RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
   3227    }   }   }
   3228
   3229    return dictPtr - (const BYTE*)dict;
   3230}
   3231
   3232/* Dictionary format :
   3233 * See :
   3234 * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format
   3235 */
   3236/*! ZSTD_loadZstdDictionary() :
   3237 * @return : dictID, or an error code
   3238 *  assumptions : magic number supposed already checked
   3239 *                dictSize supposed >= 8
   3240 */
   3241static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
   3242                                      ZSTD_matchState_t* ms,
   3243                                      ZSTD_cwksp* ws,
   3244                                      ZSTD_CCtx_params const* params,
   3245                                      const void* dict, size_t dictSize,
   3246                                      ZSTD_dictTableLoadMethod_e dtlm,
   3247                                      void* workspace)
   3248{
   3249    const BYTE* dictPtr = (const BYTE*)dict;
   3250    const BYTE* const dictEnd = dictPtr + dictSize;
   3251    size_t dictID;
   3252    size_t eSize;
   3253
   3254    ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
   3255    assert(dictSize >= 8);
   3256    assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
   3257
   3258    dictID = params->fParams.noDictIDFlag ? 0 :  MEM_readLE32(dictPtr + 4 /* skip magic number */ );
   3259    eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);
   3260    FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
   3261    dictPtr += eSize;
   3262
   3263    {
   3264        size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
   3265        FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
   3266            ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
   3267    }
   3268    return dictID;
   3269}
   3270
   3271/* ZSTD_compress_insertDictionary() :
   3272*   @return : dictID, or an error code */
   3273static size_t
   3274ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
   3275                               ZSTD_matchState_t* ms,
   3276                               ldmState_t* ls,
   3277                               ZSTD_cwksp* ws,
   3278                         const ZSTD_CCtx_params* params,
   3279                         const void* dict, size_t dictSize,
   3280                               ZSTD_dictContentType_e dictContentType,
   3281                               ZSTD_dictTableLoadMethod_e dtlm,
   3282                               void* workspace)
   3283{
   3284    DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
   3285    if ((dict==NULL) || (dictSize<8)) {
   3286        RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
   3287        return 0;
   3288    }
   3289
   3290    ZSTD_reset_compressedBlockState(bs);
   3291
   3292    /* dict restricted modes */
   3293    if (dictContentType == ZSTD_dct_rawContent)
   3294        return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm);
   3295
   3296    if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
   3297        if (dictContentType == ZSTD_dct_auto) {
   3298            DEBUGLOG(4, "raw content dictionary detected");
   3299            return ZSTD_loadDictionaryContent(
   3300                ms, ls, ws, params, dict, dictSize, dtlm);
   3301        }
   3302        RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
   3303        assert(0);   /* impossible */
   3304    }
   3305
   3306    /* dict as full zstd dictionary */
   3307    return ZSTD_loadZstdDictionary(
   3308        bs, ms, ws, params, dict, dictSize, dtlm, workspace);
   3309}
   3310
   3311#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
   3312#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL)
   3313
   3314/*! ZSTD_compressBegin_internal() :
   3315 * @return : 0, or an error code */
   3316static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
   3317                                    const void* dict, size_t dictSize,
   3318                                    ZSTD_dictContentType_e dictContentType,
   3319                                    ZSTD_dictTableLoadMethod_e dtlm,
   3320                                    const ZSTD_CDict* cdict,
   3321                                    const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
   3322                                    ZSTD_buffered_policy_e zbuff)
   3323{
   3324    DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
   3325    /* params are supposed to be fully validated at this point */
   3326    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
   3327    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */
   3328    if ( (cdict)
   3329      && (cdict->dictContentSize > 0)
   3330      && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
   3331        || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
   3332        || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
   3333        || cdict->compressionLevel == 0)
   3334      && (params->attachDictPref != ZSTD_dictForceLoad) ) {
   3335        return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
   3336    }
   3337
   3338    FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize,
   3339                                     ZSTDcrp_makeClean, zbuff) , "");
   3340    {   size_t const dictID = cdict ?
   3341                ZSTD_compress_insertDictionary(
   3342                        cctx->blockState.prevCBlock, &cctx->blockState.matchState,
   3343                        &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
   3344                        cdict->dictContentSize, cdict->dictContentType, dtlm,
   3345                        cctx->entropyWorkspace)
   3346              : ZSTD_compress_insertDictionary(
   3347                        cctx->blockState.prevCBlock, &cctx->blockState.matchState,
   3348                        &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize,
   3349                        dictContentType, dtlm, cctx->entropyWorkspace);
   3350        FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
   3351        assert(dictID <= UINT_MAX);
   3352        cctx->dictID = (U32)dictID;
   3353        cctx->dictContentSize = cdict ? cdict->dictContentSize : dictSize;
   3354    }
   3355    return 0;
   3356}
   3357
   3358size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
   3359                                    const void* dict, size_t dictSize,
   3360                                    ZSTD_dictContentType_e dictContentType,
   3361                                    ZSTD_dictTableLoadMethod_e dtlm,
   3362                                    const ZSTD_CDict* cdict,
   3363                                    const ZSTD_CCtx_params* params,
   3364                                    unsigned long long pledgedSrcSize)
   3365{
   3366    DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog);
   3367    /* compression parameters verification and optimization */
   3368    FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , "");
   3369    return ZSTD_compressBegin_internal(cctx,
   3370                                       dict, dictSize, dictContentType, dtlm,
   3371                                       cdict,
   3372                                       params, pledgedSrcSize,
   3373                                       ZSTDb_not_buffered);
   3374}
   3375
   3376/*! ZSTD_compressBegin_advanced() :
   3377*   @return : 0, or an error code */
   3378size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
   3379                             const void* dict, size_t dictSize,
   3380                                   ZSTD_parameters params, unsigned long long pledgedSrcSize)
   3381{
   3382    ZSTD_CCtx_params cctxParams;
   3383    ZSTD_CCtxParams_init_internal(&cctxParams, &params, ZSTD_NO_CLEVEL);
   3384    return ZSTD_compressBegin_advanced_internal(cctx,
   3385                                            dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
   3386                                            NULL /*cdict*/,
   3387                                            &cctxParams, pledgedSrcSize);
   3388}
   3389
   3390size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
   3391{
   3392    ZSTD_CCtx_params cctxParams;
   3393    {
   3394        ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict);
   3395        ZSTD_CCtxParams_init_internal(&cctxParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel);
   3396    }
   3397    DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
   3398    return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
   3399                                       &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
   3400}
   3401
   3402size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
   3403{
   3404    return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
   3405}
   3406
   3407
   3408/*! ZSTD_writeEpilogue() :
   3409*   Ends a frame.
   3410*   @return : nb of bytes written into dst (or an error code) */
   3411static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
   3412{
   3413    BYTE* const ostart = (BYTE*)dst;
   3414    BYTE* op = ostart;
   3415    size_t fhSize = 0;
   3416
   3417    DEBUGLOG(4, "ZSTD_writeEpilogue");
   3418    RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
   3419
   3420    /* special case : empty frame */
   3421    if (cctx->stage == ZSTDcs_init) {
   3422        fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
   3423        FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
   3424        dstCapacity -= fhSize;
   3425        op += fhSize;
   3426        cctx->stage = ZSTDcs_ongoing;
   3427    }
   3428
   3429    if (cctx->stage != ZSTDcs_ending) {
   3430        /* write one last empty block, make it the "last" block */
   3431        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
   3432        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
   3433        MEM_writeLE32(op, cBlockHeader24);
   3434        op += ZSTD_blockHeaderSize;
   3435        dstCapacity -= ZSTD_blockHeaderSize;
   3436    }
   3437
   3438    if (cctx->appliedParams.fParams.checksumFlag) {
   3439        U32 const checksum = (U32) xxh64_digest(&cctx->xxhState);
   3440        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
   3441        DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
   3442        MEM_writeLE32(op, checksum);
   3443        op += 4;
   3444    }
   3445
   3446    cctx->stage = ZSTDcs_created;  /* return to "created but no init" status */
   3447    return op-ostart;
   3448}
   3449
   3450void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
   3451{
   3452    (void)cctx;
   3453    (void)extraCSize;
   3454}
   3455
   3456size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
   3457                         void* dst, size_t dstCapacity,
   3458                   const void* src, size_t srcSize)
   3459{
   3460    size_t endResult;
   3461    size_t const cSize = ZSTD_compressContinue_internal(cctx,
   3462                                dst, dstCapacity, src, srcSize,
   3463                                1 /* frame mode */, 1 /* last chunk */);
   3464    FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed");
   3465    endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
   3466    FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
   3467    assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
   3468    if (cctx->pledgedSrcSizePlusOne != 0) {  /* control src size */
   3469        ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
   3470        DEBUGLOG(4, "end of frame : controlling src size");
   3471        RETURN_ERROR_IF(
   3472            cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
   3473            srcSize_wrong,
   3474             "error : pledgedSrcSize = %u, while realSrcSize = %u",
   3475            (unsigned)cctx->pledgedSrcSizePlusOne-1,
   3476            (unsigned)cctx->consumedSrcSize);
   3477    }
   3478    ZSTD_CCtx_trace(cctx, endResult);
   3479    return cSize + endResult;
   3480}
   3481
   3482size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
   3483                               void* dst, size_t dstCapacity,
   3484                         const void* src, size_t srcSize,
   3485                         const void* dict,size_t dictSize,
   3486                               ZSTD_parameters params)
   3487{
   3488    ZSTD_CCtx_params cctxParams;
   3489    DEBUGLOG(4, "ZSTD_compress_advanced");
   3490    FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
   3491    ZSTD_CCtxParams_init_internal(&cctxParams, &params, ZSTD_NO_CLEVEL);
   3492    return ZSTD_compress_advanced_internal(cctx,
   3493                                           dst, dstCapacity,
   3494                                           src, srcSize,
   3495                                           dict, dictSize,
   3496                                           &cctxParams);
   3497}
   3498
   3499/* Internal */
   3500size_t ZSTD_compress_advanced_internal(
   3501        ZSTD_CCtx* cctx,
   3502        void* dst, size_t dstCapacity,
   3503        const void* src, size_t srcSize,
   3504        const void* dict,size_t dictSize,
   3505        const ZSTD_CCtx_params* params)
   3506{
   3507    DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
   3508    FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
   3509                         dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
   3510                         params, srcSize, ZSTDb_not_buffered) , "");
   3511    return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
   3512}
   3513
   3514size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
   3515                               void* dst, size_t dstCapacity,
   3516                         const void* src, size_t srcSize,
   3517                         const void* dict, size_t dictSize,
   3518                               int compressionLevel)
   3519{
   3520    ZSTD_CCtx_params cctxParams;
   3521    {
   3522        ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict);
   3523        assert(params.fParams.contentSizeFlag == 1);
   3524        ZSTD_CCtxParams_init_internal(&cctxParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel);
   3525    }
   3526    DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize);
   3527    return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams);
   3528}
   3529
   3530size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
   3531                         void* dst, size_t dstCapacity,
   3532                   const void* src, size_t srcSize,
   3533                         int compressionLevel)
   3534{
   3535    DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (unsigned)srcSize);
   3536    assert(cctx != NULL);
   3537    return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
   3538}
   3539
   3540size_t ZSTD_compress(void* dst, size_t dstCapacity,
   3541               const void* src, size_t srcSize,
   3542                     int compressionLevel)
   3543{
   3544    size_t result;
   3545    ZSTD_CCtx* cctx = ZSTD_createCCtx();
   3546    RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed");
   3547    result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);
   3548    ZSTD_freeCCtx(cctx);
   3549    return result;
   3550}
   3551
   3552
   3553/* =====  Dictionary API  ===== */
   3554
   3555/*! ZSTD_estimateCDictSize_advanced() :
   3556 *  Estimate amount of memory that will be needed to create a dictionary with following arguments */
   3557size_t ZSTD_estimateCDictSize_advanced(
   3558        size_t dictSize, ZSTD_compressionParameters cParams,
   3559        ZSTD_dictLoadMethod_e dictLoadMethod)
   3560{
   3561    DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
   3562    return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
   3563         + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
   3564         + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
   3565         + (dictLoadMethod == ZSTD_dlm_byRef ? 0
   3566            : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));
   3567}
   3568
   3569size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
   3570{
   3571    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
   3572    return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
   3573}
   3574
   3575size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
   3576{
   3577    if (cdict==NULL) return 0;   /* support sizeof on NULL */
   3578    DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
   3579    /* cdict may be in the workspace */
   3580    return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))
   3581        + ZSTD_cwksp_sizeof(&cdict->workspace);
   3582}
   3583
   3584static size_t ZSTD_initCDict_internal(
   3585                    ZSTD_CDict* cdict,
   3586              const void* dictBuffer, size_t dictSize,
   3587                    ZSTD_dictLoadMethod_e dictLoadMethod,
   3588                    ZSTD_dictContentType_e dictContentType,
   3589                    ZSTD_CCtx_params params)
   3590{
   3591    DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType);
   3592    assert(!ZSTD_checkCParams(params.cParams));
   3593    cdict->matchState.cParams = params.cParams;
   3594    cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch;
   3595    if (cdict->matchState.dedicatedDictSearch && dictSize > ZSTD_CHUNKSIZE_MAX) {
   3596        cdict->matchState.dedicatedDictSearch = 0;
   3597    }
   3598    if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
   3599        cdict->dictContent = dictBuffer;
   3600    } else {
   3601         void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
   3602        RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
   3603        cdict->dictContent = internalBuffer;
   3604        ZSTD_memcpy(internalBuffer, dictBuffer, dictSize);
   3605    }
   3606    cdict->dictContentSize = dictSize;
   3607    cdict->dictContentType = dictContentType;
   3608
   3609    cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
   3610
   3611
   3612    /* Reset the state to no dictionary */
   3613    ZSTD_reset_compressedBlockState(&cdict->cBlockState);
   3614    FORWARD_IF_ERROR(ZSTD_reset_matchState(
   3615        &cdict->matchState,
   3616        &cdict->workspace,
   3617        &params.cParams,
   3618        ZSTDcrp_makeClean,
   3619        ZSTDirp_reset,
   3620        ZSTD_resetTarget_CDict), "");
   3621    /* (Maybe) load the dictionary
   3622     * Skips loading the dictionary if it is < 8 bytes.
   3623     */
   3624    {   params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
   3625        params.fParams.contentSizeFlag = 1;
   3626        {   size_t const dictID = ZSTD_compress_insertDictionary(
   3627                    &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
   3628                    &params, cdict->dictContent, cdict->dictContentSize,
   3629                    dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace);
   3630            FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
   3631            assert(dictID <= (size_t)(U32)-1);
   3632            cdict->dictID = (U32)dictID;
   3633        }
   3634    }
   3635
   3636    return 0;
   3637}
   3638
   3639static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize,
   3640                                      ZSTD_dictLoadMethod_e dictLoadMethod,
   3641                                      ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
   3642{
   3643    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
   3644
   3645    {   size_t const workspaceSize =
   3646            ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +
   3647            ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +
   3648            ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) +
   3649            (dictLoadMethod == ZSTD_dlm_byRef ? 0
   3650             : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));
   3651        void* const workspace = ZSTD_customMalloc(workspaceSize, customMem);
   3652        ZSTD_cwksp ws;
   3653        ZSTD_CDict* cdict;
   3654
   3655        if (!workspace) {
   3656            ZSTD_customFree(workspace, customMem);
   3657            return NULL;
   3658        }
   3659
   3660        ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc);
   3661
   3662        cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
   3663        assert(cdict != NULL);
   3664        ZSTD_cwksp_move(&cdict->workspace, &ws);
   3665        cdict->customMem = customMem;
   3666        cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */
   3667
   3668        return cdict;
   3669    }
   3670}
   3671
   3672ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
   3673                                      ZSTD_dictLoadMethod_e dictLoadMethod,
   3674                                      ZSTD_dictContentType_e dictContentType,
   3675                                      ZSTD_compressionParameters cParams,
   3676                                      ZSTD_customMem customMem)
   3677{
   3678    ZSTD_CCtx_params cctxParams;
   3679    ZSTD_memset(&cctxParams, 0, sizeof(cctxParams));
   3680    ZSTD_CCtxParams_init(&cctxParams, 0);
   3681    cctxParams.cParams = cParams;
   3682    cctxParams.customMem = customMem;
   3683    return ZSTD_createCDict_advanced2(
   3684        dictBuffer, dictSize,
   3685        dictLoadMethod, dictContentType,
   3686        &cctxParams, customMem);
   3687}
   3688
   3689ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
   3690        const void* dict, size_t dictSize,
   3691        ZSTD_dictLoadMethod_e dictLoadMethod,
   3692        ZSTD_dictContentType_e dictContentType,
   3693        const ZSTD_CCtx_params* originalCctxParams,
   3694        ZSTD_customMem customMem)
   3695{
   3696    ZSTD_CCtx_params cctxParams = *originalCctxParams;
   3697    ZSTD_compressionParameters cParams;
   3698    ZSTD_CDict* cdict;
   3699
   3700    DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType);
   3701    if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
   3702
   3703    if (cctxParams.enableDedicatedDictSearch) {
   3704        cParams = ZSTD_dedicatedDictSearch_getCParams(
   3705            cctxParams.compressionLevel, dictSize);
   3706        ZSTD_overrideCParams(&cParams, &cctxParams.cParams);
   3707    } else {
   3708        cParams = ZSTD_getCParamsFromCCtxParams(
   3709            &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
   3710    }
   3711
   3712    if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) {
   3713        /* Fall back to non-DDSS params */
   3714        cctxParams.enableDedicatedDictSearch = 0;
   3715        cParams = ZSTD_getCParamsFromCCtxParams(
   3716            &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
   3717    }
   3718
   3719    cctxParams.cParams = cParams;
   3720
   3721    cdict = ZSTD_createCDict_advanced_internal(dictSize,
   3722                        dictLoadMethod, cctxParams.cParams,
   3723                        customMem);
   3724
   3725    if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
   3726                                    dict, dictSize,
   3727                                    dictLoadMethod, dictContentType,
   3728                                    cctxParams) )) {
   3729        ZSTD_freeCDict(cdict);
   3730        return NULL;
   3731    }
   3732
   3733    return cdict;
   3734}
   3735
   3736ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
   3737{
   3738    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
   3739    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
   3740                                                  ZSTD_dlm_byCopy, ZSTD_dct_auto,
   3741                                                  cParams, ZSTD_defaultCMem);
   3742    if (cdict)
   3743        cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
   3744    return cdict;
   3745}
   3746
   3747ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
   3748{
   3749    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
   3750    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
   3751                                     ZSTD_dlm_byRef, ZSTD_dct_auto,
   3752                                     cParams, ZSTD_defaultCMem);
   3753    if (cdict)
   3754        cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
   3755    return cdict;
   3756}
   3757
   3758size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
   3759{
   3760    if (cdict==NULL) return 0;   /* support free on NULL */
   3761    {   ZSTD_customMem const cMem = cdict->customMem;
   3762        int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);
   3763        ZSTD_cwksp_free(&cdict->workspace, cMem);
   3764        if (!cdictInWorkspace) {
   3765            ZSTD_customFree(cdict, cMem);
   3766        }
   3767        return 0;
   3768    }
   3769}
   3770
   3771/*! ZSTD_initStaticCDict_advanced() :
   3772 *  Generate a digested dictionary in provided memory area.
   3773 *  workspace: The memory area to emplace the dictionary into.
   3774 *             Provided pointer must 8-bytes aligned.
   3775 *             It must outlive dictionary usage.
   3776 *  workspaceSize: Use ZSTD_estimateCDictSize()
   3777 *                 to determine how large workspace must be.
   3778 *  cParams : use ZSTD_getCParams() to transform a compression level
   3779 *            into its relevants cParams.
   3780 * @return : pointer to ZSTD_CDict*, or NULL if error (size too small)
   3781 *  Note : there is no corresponding "free" function.
   3782 *         Since workspace was allocated externally, it must be freed externally.
   3783 */
   3784const ZSTD_CDict* ZSTD_initStaticCDict(
   3785                                 void* workspace, size_t workspaceSize,
   3786                           const void* dict, size_t dictSize,
   3787                                 ZSTD_dictLoadMethod_e dictLoadMethod,
   3788                                 ZSTD_dictContentType_e dictContentType,
   3789                                 ZSTD_compressionParameters cParams)
   3790{
   3791    size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
   3792    size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
   3793                            + (dictLoadMethod == ZSTD_dlm_byRef ? 0
   3794                               : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))
   3795                            + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
   3796                            + matchStateSize;
   3797    ZSTD_CDict* cdict;
   3798    ZSTD_CCtx_params params;
   3799
   3800    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */
   3801
   3802    {
   3803        ZSTD_cwksp ws;
   3804        ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
   3805        cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
   3806        if (cdict == NULL) return NULL;
   3807        ZSTD_cwksp_move(&cdict->workspace, &ws);
   3808    }
   3809
   3810    DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
   3811        (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
   3812    if (workspaceSize < neededSize) return NULL;
   3813
   3814    ZSTD_CCtxParams_init(&params, 0);
   3815    params.cParams = cParams;
   3816
   3817    if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
   3818                                              dict, dictSize,
   3819                                              dictLoadMethod, dictContentType,
   3820                                              params) ))
   3821        return NULL;
   3822
   3823    return cdict;
   3824}
   3825
   3826ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
   3827{
   3828    assert(cdict != NULL);
   3829    return cdict->matchState.cParams;
   3830}
   3831
   3832/*! ZSTD_getDictID_fromCDict() :
   3833 *  Provides the dictID of the dictionary loaded into `cdict`.
   3834 *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
   3835 *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
   3836unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)
   3837{
   3838    if (cdict==NULL) return 0;
   3839    return cdict->dictID;
   3840}
   3841
   3842
   3843/* ZSTD_compressBegin_usingCDict_advanced() :
   3844 * cdict must be != NULL */
   3845size_t ZSTD_compressBegin_usingCDict_advanced(
   3846    ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
   3847    ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
   3848{
   3849    ZSTD_CCtx_params cctxParams;
   3850    DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
   3851    RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
   3852    /* Initialize the cctxParams from the cdict */
   3853    {
   3854        ZSTD_parameters params;
   3855        params.fParams = fParams;
   3856        params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
   3857                        || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
   3858                        || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
   3859                        || cdict->compressionLevel == 0 ) ?
   3860                ZSTD_getCParamsFromCDict(cdict)
   3861              : ZSTD_getCParams(cdict->compressionLevel,
   3862                                pledgedSrcSize,
   3863                                cdict->dictContentSize);
   3864        ZSTD_CCtxParams_init_internal(&cctxParams, &params, cdict->compressionLevel);
   3865    }
   3866    /* Increase window log to fit the entire dictionary and source if the
   3867     * source size is known. Limit the increase to 19, which is the
   3868     * window log for compression level 1 with the largest source size.
   3869     */
   3870    if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
   3871        U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
   3872        U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
   3873        cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog);
   3874    }
   3875    return ZSTD_compressBegin_internal(cctx,
   3876                                        NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
   3877                                        cdict,
   3878                                        &cctxParams, pledgedSrcSize,
   3879                                        ZSTDb_not_buffered);
   3880}
   3881
   3882/* ZSTD_compressBegin_usingCDict() :
   3883 * pledgedSrcSize=0 means "unknown"
   3884 * if pledgedSrcSize>0, it will enable contentSizeFlag */
   3885size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
   3886{
   3887    ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
   3888    DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
   3889    return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
   3890}
   3891
   3892size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
   3893                                void* dst, size_t dstCapacity,
   3894                                const void* src, size_t srcSize,
   3895                                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
   3896{
   3897    FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), "");   /* will check if cdict != NULL */
   3898    return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
   3899}
   3900
   3901/*! ZSTD_compress_usingCDict() :
   3902 *  Compression using a digested Dictionary.
   3903 *  Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
   3904 *  Note that compression parameters are decided at CDict creation time
   3905 *  while frame parameters are hardcoded */
   3906size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
   3907                                void* dst, size_t dstCapacity,
   3908                                const void* src, size_t srcSize,
   3909                                const ZSTD_CDict* cdict)
   3910{
   3911    ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
   3912    return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
   3913}
   3914
   3915
   3916
   3917/* ******************************************************************
   3918*  Streaming
   3919********************************************************************/
   3920
   3921ZSTD_CStream* ZSTD_createCStream(void)
   3922{
   3923    DEBUGLOG(3, "ZSTD_createCStream");
   3924    return ZSTD_createCStream_advanced(ZSTD_defaultCMem);
   3925}
   3926
   3927ZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize)
   3928{
   3929    return ZSTD_initStaticCCtx(workspace, workspaceSize);
   3930}
   3931
   3932ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
   3933{   /* CStream and CCtx are now same object */
   3934    return ZSTD_createCCtx_advanced(customMem);
   3935}
   3936
   3937size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
   3938{
   3939    return ZSTD_freeCCtx(zcs);   /* same object */
   3940}
   3941
   3942
   3943
   3944/*======   Initialization   ======*/
   3945
   3946size_t ZSTD_CStreamInSize(void)  { return ZSTD_BLOCKSIZE_MAX; }
   3947
   3948size_t ZSTD_CStreamOutSize(void)
   3949{
   3950    return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
   3951}
   3952
   3953static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)
   3954{
   3955    if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))
   3956        return ZSTD_cpm_attachDict;
   3957    else
   3958        return ZSTD_cpm_noAttachDict;
   3959}
   3960
   3961/* ZSTD_resetCStream():
   3962 * pledgedSrcSize == 0 means "unknown" */
   3963size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
   3964{
   3965    /* temporary : 0 interpreted as "unknown" during transition period.
   3966     * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
   3967     * 0 will be interpreted as "empty" in the future.
   3968     */
   3969    U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
   3970    DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
   3971    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   3972    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
   3973    return 0;
   3974}
   3975
   3976/*! ZSTD_initCStream_internal() :
   3977 *  Note : for lib/compress only. Used by zstdmt_compress.c.
   3978 *  Assumption 1 : params are valid
   3979 *  Assumption 2 : either dict, or cdict, is defined, not both */
   3980size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
   3981                    const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
   3982                    const ZSTD_CCtx_params* params,
   3983                    unsigned long long pledgedSrcSize)
   3984{
   3985    DEBUGLOG(4, "ZSTD_initCStream_internal");
   3986    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   3987    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
   3988    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
   3989    zcs->requestedParams = *params;
   3990    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */
   3991    if (dict) {
   3992        FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
   3993    } else {
   3994        /* Dictionary is cleared if !cdict */
   3995        FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
   3996    }
   3997    return 0;
   3998}
   3999
   4000/* ZSTD_initCStream_usingCDict_advanced() :
   4001 * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
   4002size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
   4003                                            const ZSTD_CDict* cdict,
   4004                                            ZSTD_frameParameters fParams,
   4005                                            unsigned long long pledgedSrcSize)
   4006{
   4007    DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
   4008    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   4009    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
   4010    zcs->requestedParams.fParams = fParams;
   4011    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
   4012    return 0;
   4013}
   4014
   4015/* note : cdict must outlive compression session */
   4016size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
   4017{
   4018    DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
   4019    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   4020    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
   4021    return 0;
   4022}
   4023
   4024
   4025/* ZSTD_initCStream_advanced() :
   4026 * pledgedSrcSize must be exact.
   4027 * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
   4028 * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */
   4029size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
   4030                                 const void* dict, size_t dictSize,
   4031                                 ZSTD_parameters params, unsigned long long pss)
   4032{
   4033    /* for compatibility with older programs relying on this behavior.
   4034     * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
   4035     * This line will be removed in the future.
   4036     */
   4037    U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
   4038    DEBUGLOG(4, "ZSTD_initCStream_advanced");
   4039    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   4040    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
   4041    FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
   4042    ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, &params);
   4043    FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
   4044    return 0;
   4045}
   4046
   4047size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
   4048{
   4049    DEBUGLOG(4, "ZSTD_initCStream_usingDict");
   4050    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   4051    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
   4052    FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
   4053    return 0;
   4054}
   4055
   4056size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
   4057{
   4058    /* temporary : 0 interpreted as "unknown" during transition period.
   4059     * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
   4060     * 0 will be interpreted as "empty" in the future.
   4061     */
   4062    U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
   4063    DEBUGLOG(4, "ZSTD_initCStream_srcSize");
   4064    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   4065    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
   4066    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
   4067    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
   4068    return 0;
   4069}
   4070
   4071size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
   4072{
   4073    DEBUGLOG(4, "ZSTD_initCStream");
   4074    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
   4075    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
   4076    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
   4077    return 0;
   4078}
   4079
   4080/*======   Compression   ======*/
   4081
   4082static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
   4083{
   4084    size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos;
   4085    if (hintInSize==0) hintInSize = cctx->blockSize;
   4086    return hintInSize;
   4087}
   4088
   4089/* ZSTD_compressStream_generic():
   4090 *  internal function for all *compressStream*() variants
   4091 *  non-static, because can be called from zstdmt_compress.c
   4092 * @return : hint size for next input */
   4093static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
   4094                                          ZSTD_outBuffer* output,
   4095                                          ZSTD_inBuffer* input,
   4096                                          ZSTD_EndDirective const flushMode)
   4097{
   4098    const char* const istart = (const char*)input->src;
   4099    const char* const iend = input->size != 0 ? istart + input->size : istart;
   4100    const char* ip = input->pos != 0 ? istart + input->pos : istart;
   4101    char* const ostart = (char*)output->dst;
   4102    char* const oend = output->size != 0 ? ostart + output->size : ostart;
   4103    char* op = output->pos != 0 ? ostart + output->pos : ostart;
   4104    U32 someMoreWork = 1;
   4105
   4106    /* check expectations */
   4107    DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode);
   4108    if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
   4109        assert(zcs->inBuff != NULL);
   4110        assert(zcs->inBuffSize > 0);
   4111    }
   4112    if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) {
   4113        assert(zcs->outBuff !=  NULL);
   4114        assert(zcs->outBuffSize > 0);
   4115    }
   4116    assert(output->pos <= output->size);
   4117    assert(input->pos <= input->size);
   4118    assert((U32)flushMode <= (U32)ZSTD_e_end);
   4119
   4120    while (someMoreWork) {
   4121        switch(zcs->streamStage)
   4122        {
   4123        case zcss_init:
   4124            RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
   4125
   4126        case zcss_load:
   4127            if ( (flushMode == ZSTD_e_end)
   4128              && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip)     /* Enough output space */
   4129                || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)  /* OR we are allowed to return dstSizeTooSmall */
   4130              && (zcs->inBuffPos == 0) ) {
   4131                /* shortcut to compression pass directly into output buffer */
   4132                size_t const cSize = ZSTD_compressEnd(zcs,
   4133                                                op, oend-op, ip, iend-ip);
   4134                DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
   4135                FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed");
   4136                ip = iend;
   4137                op += cSize;
   4138                zcs->frameEnded = 1;
   4139                ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
   4140                someMoreWork = 0; break;
   4141            }
   4142            /* complete loading into inBuffer in buffered mode */
   4143            if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
   4144                size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
   4145                size_t const loaded = ZSTD_limitCopy(
   4146                                        zcs->inBuff + zcs->inBuffPos, toLoad,
   4147                                        ip, iend-ip);
   4148                zcs->inBuffPos += loaded;
   4149                if (loaded != 0)
   4150                    ip += loaded;
   4151                if ( (flushMode == ZSTD_e_continue)
   4152                  && (zcs->inBuffPos < zcs->inBuffTarget) ) {
   4153                    /* not enough input to fill full block : stop here */
   4154                    someMoreWork = 0; break;
   4155                }
   4156                if ( (flushMode == ZSTD_e_flush)
   4157                  && (zcs->inBuffPos == zcs->inToCompress) ) {
   4158                    /* empty */
   4159                    someMoreWork = 0; break;
   4160                }
   4161            }
   4162            /* compress current block (note : this stage cannot be stopped in the middle) */
   4163            DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode);
   4164            {   int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered);
   4165                void* cDst;
   4166                size_t cSize;
   4167                size_t oSize = oend-op;
   4168                size_t const iSize = inputBuffered
   4169                    ? zcs->inBuffPos - zcs->inToCompress
   4170                    : MIN((size_t)(iend - ip), zcs->blockSize);
   4171                if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)
   4172                    cDst = op;   /* compress into output buffer, to skip flush stage */
   4173                else
   4174                    cDst = zcs->outBuff, oSize = zcs->outBuffSize;
   4175                if (inputBuffered) {
   4176                    unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
   4177                    cSize = lastBlock ?
   4178                            ZSTD_compressEnd(zcs, cDst, oSize,
   4179                                        zcs->inBuff + zcs->inToCompress, iSize) :
   4180                            ZSTD_compressContinue(zcs, cDst, oSize,
   4181                                        zcs->inBuff + zcs->inToCompress, iSize);
   4182                    FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
   4183                    zcs->frameEnded = lastBlock;
   4184                    /* prepare next block */
   4185                    zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
   4186                    if (zcs->inBuffTarget > zcs->inBuffSize)
   4187                        zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
   4188                    DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
   4189                            (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);
   4190                    if (!lastBlock)
   4191                        assert(zcs->inBuffTarget <= zcs->inBuffSize);
   4192                    zcs->inToCompress = zcs->inBuffPos;
   4193                } else {
   4194                    unsigned const lastBlock = (ip + iSize == iend);
   4195                    assert(flushMode == ZSTD_e_end /* Already validated */);
   4196                    cSize = lastBlock ?
   4197                            ZSTD_compressEnd(zcs, cDst, oSize, ip, iSize) :
   4198                            ZSTD_compressContinue(zcs, cDst, oSize, ip, iSize);
   4199                    /* Consume the input prior to error checking to mirror buffered mode. */
   4200                    if (iSize > 0)
   4201                        ip += iSize;
   4202                    FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
   4203                    zcs->frameEnded = lastBlock;
   4204                    if (lastBlock)
   4205                        assert(ip == iend);
   4206                }
   4207                if (cDst == op) {  /* no need to flush */
   4208                    op += cSize;
   4209                    if (zcs->frameEnded) {
   4210                        DEBUGLOG(5, "Frame completed directly in outBuffer");
   4211                        someMoreWork = 0;
   4212                        ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
   4213                    }
   4214                    break;
   4215                }
   4216                zcs->outBuffContentSize = cSize;
   4217                zcs->outBuffFlushedSize = 0;
   4218                zcs->streamStage = zcss_flush; /* pass-through to flush stage */
   4219            }
   4220	    ZSTD_FALLTHROUGH;
   4221        case zcss_flush:
   4222            DEBUGLOG(5, "flush stage");
   4223            assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);
   4224            {   size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
   4225                size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
   4226                            zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
   4227                DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
   4228                            (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
   4229                if (flushed)
   4230                    op += flushed;
   4231                zcs->outBuffFlushedSize += flushed;
   4232                if (toFlush!=flushed) {
   4233                    /* flush not fully completed, presumably because dst is too small */
   4234                    assert(op==oend);
   4235                    someMoreWork = 0;
   4236                    break;
   4237                }
   4238                zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
   4239                if (zcs->frameEnded) {
   4240                    DEBUGLOG(5, "Frame completed on flush");
   4241                    someMoreWork = 0;
   4242                    ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
   4243                    break;
   4244                }
   4245                zcs->streamStage = zcss_load;
   4246                break;
   4247            }
   4248
   4249        default: /* impossible */
   4250            assert(0);
   4251        }
   4252    }
   4253
   4254    input->pos = ip - istart;
   4255    output->pos = op - ostart;
   4256    if (zcs->frameEnded) return 0;
   4257    return ZSTD_nextInputSizeHint(zcs);
   4258}
   4259
   4260static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
   4261{
   4262    return ZSTD_nextInputSizeHint(cctx);
   4263
   4264}
   4265
   4266size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
   4267{
   4268    FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , "");
   4269    return ZSTD_nextInputSizeHint_MTorST(zcs);
   4270}
   4271
   4272/* After a compression call set the expected input/output buffer.
   4273 * This is validated at the start of the next compression call.
   4274 */
   4275static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input)
   4276{
   4277    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
   4278        cctx->expectedInBuffer = *input;
   4279    }
   4280    if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
   4281        cctx->expectedOutBufferSize = output->size - output->pos;
   4282    }
   4283}
   4284
   4285/* Validate that the input/output buffers match the expectations set by
   4286 * ZSTD_setBufferExpectations.
   4287 */
   4288static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
   4289                                        ZSTD_outBuffer const* output,
   4290                                        ZSTD_inBuffer const* input,
   4291                                        ZSTD_EndDirective endOp)
   4292{
   4293    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
   4294        ZSTD_inBuffer const expect = cctx->expectedInBuffer;
   4295        if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size)
   4296            RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!");
   4297        if (endOp != ZSTD_e_end)
   4298            RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!");
   4299    }
   4300    if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
   4301        size_t const outBufferSize = output->size - output->pos;
   4302        if (cctx->expectedOutBufferSize != outBufferSize)
   4303            RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!");
   4304    }
   4305    return 0;
   4306}
   4307
   4308static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
   4309                                             ZSTD_EndDirective endOp,
   4310                                             size_t inSize) {
   4311    ZSTD_CCtx_params params = cctx->requestedParams;
   4312    ZSTD_prefixDict const prefixDict = cctx->prefixDict;
   4313    FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
   4314    ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));   /* single usage */
   4315    assert(prefixDict.dict==NULL || cctx->cdict==NULL);    /* only one can be set */
   4316    if (cctx->cdict)
   4317        params.compressionLevel = cctx->cdict->compressionLevel; /* let cdict take priority in terms of compression level */
   4318    DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
   4319    if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1;  /* auto-fix pledgedSrcSize */
   4320    {
   4321        size_t const dictSize = prefixDict.dict
   4322                ? prefixDict.dictSize
   4323                : (cctx->cdict ? cctx->cdict->dictContentSize : 0);
   4324        ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, &params, cctx->pledgedSrcSizePlusOne - 1);
   4325        params.cParams = ZSTD_getCParamsFromCCtxParams(
   4326                &params, cctx->pledgedSrcSizePlusOne-1,
   4327                dictSize, mode);
   4328    }
   4329
   4330    if (ZSTD_CParams_shouldEnableLdm(&params.cParams)) {
   4331        /* Enable LDM by default for optimal parser and window size >= 128MB */
   4332        DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)");
   4333        params.ldmParams.enableLdm = 1;
   4334    }
   4335
   4336    {   U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1;
   4337        assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
   4338        FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
   4339                prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast,
   4340                cctx->cdict,
   4341                &params, pledgedSrcSize,
   4342                ZSTDb_buffered) , "");
   4343        assert(cctx->appliedParams.nbWorkers == 0);
   4344        cctx->inToCompress = 0;
   4345        cctx->inBuffPos = 0;
   4346        if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) {
   4347            /* for small input: avoid automatic flush on reaching end of block, since
   4348            * it would require to add a 3-bytes null block to end frame
   4349            */
   4350            cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize);
   4351        } else {
   4352            cctx->inBuffTarget = 0;
   4353        }
   4354        cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
   4355        cctx->streamStage = zcss_load;
   4356        cctx->frameEnded = 0;
   4357    }
   4358    return 0;
   4359}
   4360
   4361size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
   4362                             ZSTD_outBuffer* output,
   4363                             ZSTD_inBuffer* input,
   4364                             ZSTD_EndDirective endOp)
   4365{
   4366    DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
   4367    /* check conditions */
   4368    RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer");
   4369    RETURN_ERROR_IF(input->pos  > input->size, srcSize_wrong, "invalid input buffer");
   4370    RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective");
   4371    assert(cctx != NULL);
   4372
   4373    /* transparent initialization stage */
   4374    if (cctx->streamStage == zcss_init) {
   4375        FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, input->size), "CompressStream2 initialization failed");
   4376        ZSTD_setBufferExpectations(cctx, output, input);    /* Set initial buffer expectations now that we've initialized */
   4377    }
   4378    /* end of transparent initialization stage */
   4379
   4380    FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers");
   4381    /* compression stage */
   4382    FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
   4383    DEBUGLOG(5, "completed ZSTD_compressStream2");
   4384    ZSTD_setBufferExpectations(cctx, output, input);
   4385    return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
   4386}
   4387
   4388size_t ZSTD_compressStream2_simpleArgs (
   4389                            ZSTD_CCtx* cctx,
   4390                            void* dst, size_t dstCapacity, size_t* dstPos,
   4391                      const void* src, size_t srcSize, size_t* srcPos,
   4392                            ZSTD_EndDirective endOp)
   4393{
   4394    ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
   4395    ZSTD_inBuffer  input  = { src, srcSize, *srcPos };
   4396    /* ZSTD_compressStream2() will check validity of dstPos and srcPos */
   4397    size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);
   4398    *dstPos = output.pos;
   4399    *srcPos = input.pos;
   4400    return cErr;
   4401}
   4402
   4403size_t ZSTD_compress2(ZSTD_CCtx* cctx,
   4404                      void* dst, size_t dstCapacity,
   4405                      const void* src, size_t srcSize)
   4406{
   4407    ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;
   4408    ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;
   4409    DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
   4410    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
   4411    /* Enable stable input/output buffers. */
   4412    cctx->requestedParams.inBufferMode = ZSTD_bm_stable;
   4413    cctx->requestedParams.outBufferMode = ZSTD_bm_stable;
   4414    {   size_t oPos = 0;
   4415        size_t iPos = 0;
   4416        size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
   4417                                        dst, dstCapacity, &oPos,
   4418                                        src, srcSize, &iPos,
   4419                                        ZSTD_e_end);
   4420        /* Reset to the original values. */
   4421        cctx->requestedParams.inBufferMode = originalInBufferMode;
   4422        cctx->requestedParams.outBufferMode = originalOutBufferMode;
   4423        FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
   4424        if (result != 0) {  /* compression not completed, due to lack of output space */
   4425            assert(oPos == dstCapacity);
   4426            RETURN_ERROR(dstSize_tooSmall, "");
   4427        }
   4428        assert(iPos == srcSize);   /* all input is expected consumed */
   4429        return oPos;
   4430    }
   4431}
   4432
   4433typedef struct {
   4434    U32 idx;             /* Index in array of ZSTD_Sequence */
   4435    U32 posInSequence;   /* Position within sequence at idx */
   4436    size_t posInSrc;        /* Number of bytes given by sequences provided so far */
   4437} ZSTD_sequencePosition;
   4438
   4439/* Returns a ZSTD error code if sequence is not valid */
   4440static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength,
   4441                                    size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) {
   4442    size_t offsetBound;
   4443    U32 windowSize = 1 << windowLog;
   4444    /* posInSrc represents the amount of data the the decoder would decode up to this point.
   4445     * As long as the amount of data decoded is less than or equal to window size, offsets may be
   4446     * larger than the total length of output decoded in order to reference the dict, even larger than
   4447     * window size. After output surpasses windowSize, we're limited to windowSize offsets again.
   4448     */
   4449    offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
   4450    RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!");
   4451    RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small");
   4452    return 0;
   4453}
   4454
   4455/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */
   4456static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) {
   4457    U32 offCode = rawOffset + ZSTD_REP_MOVE;
   4458    U32 repCode = 0;
   4459
   4460    if (!ll0 && rawOffset == rep[0]) {
   4461        repCode = 1;
   4462    } else if (rawOffset == rep[1]) {
   4463        repCode = 2 - ll0;
   4464    } else if (rawOffset == rep[2]) {
   4465        repCode = 3 - ll0;
   4466    } else if (ll0 && rawOffset == rep[0] - 1) {
   4467        repCode = 3;
   4468    }
   4469    if (repCode) {
   4470        /* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */
   4471        offCode = repCode - 1;
   4472    }
   4473    return offCode;
   4474}
   4475
   4476/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
   4477 * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
   4478 */
   4479static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
   4480                                                             const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
   4481                                                             const void* src, size_t blockSize) {
   4482    U32 idx = seqPos->idx;
   4483    BYTE const* ip = (BYTE const*)(src);
   4484    const BYTE* const iend = ip + blockSize;
   4485    repcodes_t updatedRepcodes;
   4486    U32 dictSize;
   4487    U32 litLength;
   4488    U32 matchLength;
   4489    U32 ll0;
   4490    U32 offCode;
   4491
   4492    if (cctx->cdict) {
   4493        dictSize = (U32)cctx->cdict->dictContentSize;
   4494    } else if (cctx->prefixDict.dict) {
   4495        dictSize = (U32)cctx->prefixDict.dictSize;
   4496    } else {
   4497        dictSize = 0;
   4498    }
   4499    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
   4500    for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) {
   4501        litLength = inSeqs[idx].litLength;
   4502        matchLength = inSeqs[idx].matchLength;
   4503        ll0 = litLength == 0;
   4504        offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
   4505        updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
   4506
   4507        DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
   4508        if (cctx->appliedParams.validateSequences) {
   4509            seqPos->posInSrc += litLength + matchLength;
   4510            FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
   4511                                                cctx->appliedParams.cParams.windowLog, dictSize,
   4512                                                cctx->appliedParams.cParams.minMatch),
   4513                                                "Sequence validation failed");
   4514        }
   4515        RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
   4516                        "Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
   4517        ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
   4518        ip += matchLength + litLength;
   4519    }
   4520    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
   4521
   4522    if (inSeqs[idx].litLength) {
   4523        DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength);
   4524        ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength);
   4525        ip += inSeqs[idx].litLength;
   4526        seqPos->posInSrc += inSeqs[idx].litLength;
   4527    }
   4528    RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!");
   4529    seqPos->idx = idx+1;
   4530    return 0;
   4531}
   4532
   4533/* Returns the number of bytes to move the current read position back by. Only non-zero
   4534 * if we ended up splitting a sequence. Otherwise, it may return a ZSTD error if something
   4535 * went wrong.
   4536 *
   4537 * This function will attempt to scan through blockSize bytes represented by the sequences
   4538 * in inSeqs, storing any (partial) sequences.
   4539 *
   4540 * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
   4541 * avoid splitting a match, or to avoid splitting a match such that it would produce a match
   4542 * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
   4543 */
   4544static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
   4545                                                       const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
   4546                                                       const void* src, size_t blockSize) {
   4547    U32 idx = seqPos->idx;
   4548    U32 startPosInSequence = seqPos->posInSequence;
   4549    U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
   4550    size_t dictSize;
   4551    BYTE const* ip = (BYTE const*)(src);
   4552    BYTE const* iend = ip + blockSize;  /* May be adjusted if we decide to process fewer than blockSize bytes */
   4553    repcodes_t updatedRepcodes;
   4554    U32 bytesAdjustment = 0;
   4555    U32 finalMatchSplit = 0;
   4556    U32 litLength;
   4557    U32 matchLength;
   4558    U32 rawOffset;
   4559    U32 offCode;
   4560
   4561    if (cctx->cdict) {
   4562        dictSize = cctx->cdict->dictContentSize;
   4563    } else if (cctx->prefixDict.dict) {
   4564        dictSize = cctx->prefixDict.dictSize;
   4565    } else {
   4566        dictSize = 0;
   4567    }
   4568    DEBUGLOG(5, "ZSTD_copySequencesToSeqStore: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize);
   4569    DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
   4570    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
   4571    while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {
   4572        const ZSTD_Sequence currSeq = inSeqs[idx];
   4573        litLength = currSeq.litLength;
   4574        matchLength = currSeq.matchLength;
   4575        rawOffset = currSeq.offset;
   4576
   4577        /* Modify the sequence depending on where endPosInSequence lies */
   4578        if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {
   4579            if (startPosInSequence >= litLength) {
   4580                startPosInSequence -= litLength;
   4581                litLength = 0;
   4582                matchLength -= startPosInSequence;
   4583            } else {
   4584                litLength -= startPosInSequence;
   4585            }
   4586            /* Move to the next sequence */
   4587            endPosInSequence -= currSeq.litLength + currSeq.matchLength;
   4588            startPosInSequence = 0;
   4589            idx++;
   4590        } else {
   4591            /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence
   4592               does not reach the end of the match. So, we have to split the sequence */
   4593            DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u",
   4594                     currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence);
   4595            if (endPosInSequence > litLength) {
   4596                U32 firstHalfMatchLength;
   4597                litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence;
   4598                firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength;
   4599                if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) {
   4600                    /* Only ever split the match if it is larger than the block size */
   4601                    U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence;
   4602                    if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) {
   4603                        /* Move the endPosInSequence backward so that it creates match of minMatch length */
   4604                        endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
   4605                        bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
   4606                        firstHalfMatchLength -= bytesAdjustment;
   4607                    }
   4608                    matchLength = firstHalfMatchLength;
   4609                    /* Flag that we split the last match - after storing the sequence, exit the loop,
   4610                       but keep the value of endPosInSequence */
   4611                    finalMatchSplit = 1;
   4612                } else {
   4613                    /* Move the position in sequence backwards so that we don't split match, and break to store
   4614                     * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence
   4615                     * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so
   4616                     * would cause the first half of the match to be too small
   4617                     */
   4618                    bytesAdjustment = endPosInSequence - currSeq.litLength;
   4619                    endPosInSequence = currSeq.litLength;
   4620                    break;
   4621                }
   4622            } else {
   4623                /* This sequence ends inside the literals, break to store the last literals */
   4624                break;
   4625            }
   4626        }
   4627        /* Check if this offset can be represented with a repcode */
   4628        {   U32 ll0 = (litLength == 0);
   4629            offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0);
   4630            updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
   4631        }
   4632
   4633        if (cctx->appliedParams.validateSequences) {
   4634            seqPos->posInSrc += litLength + matchLength;
   4635            FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
   4636                                                   cctx->appliedParams.cParams.windowLog, dictSize,
   4637                                                   cctx->appliedParams.cParams.minMatch),
   4638                                                   "Sequence validation failed");
   4639        }
   4640        DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
   4641        RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
   4642                        "Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
   4643        ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
   4644        ip += matchLength + litLength;
   4645    }
   4646    DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
   4647    assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);
   4648    seqPos->idx = idx;
   4649    seqPos->posInSequence = endPosInSequence;
   4650    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
   4651
   4652    iend -= bytesAdjustment;
   4653    if (ip != iend) {
   4654        /* Store any last literals */
   4655        U32 lastLLSize = (U32)(iend - ip);
   4656        assert(ip <= iend);
   4657        DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize);
   4658        ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);
   4659        seqPos->posInSrc += lastLLSize;
   4660    }
   4661
   4662    return bytesAdjustment;
   4663}
   4664
   4665typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
   4666                                       const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
   4667                                       const void* src, size_t blockSize);
   4668static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) {
   4669    ZSTD_sequenceCopier sequenceCopier = NULL;
   4670    assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode));
   4671    if (mode == ZSTD_sf_explicitBlockDelimiters) {
   4672        return ZSTD_copySequencesToSeqStoreExplicitBlockDelim;
   4673    } else if (mode == ZSTD_sf_noBlockDelimiters) {
   4674        return ZSTD_copySequencesToSeqStoreNoBlockDelim;
   4675    }
   4676    assert(sequenceCopier != NULL);
   4677    return sequenceCopier;
   4678}
   4679
   4680/* Compress, block-by-block, all of the sequences given.
   4681 *
   4682 * Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error.
   4683 */
   4684static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
   4685                                              void* dst, size_t dstCapacity,
   4686                                              const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
   4687                                              const void* src, size_t srcSize) {
   4688    size_t cSize = 0;
   4689    U32 lastBlock;
   4690    size_t blockSize;
   4691    size_t compressedSeqsSize;
   4692    size_t remaining = srcSize;
   4693    ZSTD_sequencePosition seqPos = {0, 0, 0};
   4694
   4695    BYTE const* ip = (BYTE const*)src;
   4696    BYTE* op = (BYTE*)dst;
   4697    ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
   4698
   4699    DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize);
   4700    /* Special case: empty frame */
   4701    if (remaining == 0) {
   4702        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);
   4703        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header");
   4704        MEM_writeLE32(op, cBlockHeader24);
   4705        op += ZSTD_blockHeaderSize;
   4706        dstCapacity -= ZSTD_blockHeaderSize;
   4707        cSize += ZSTD_blockHeaderSize;
   4708    }
   4709
   4710    while (remaining) {
   4711        size_t cBlockSize;
   4712        size_t additionalByteAdjustment;
   4713        lastBlock = remaining <= cctx->blockSize;
   4714        blockSize = lastBlock ? (U32)remaining : (U32)cctx->blockSize;
   4715        ZSTD_resetSeqStore(&cctx->seqStore);
   4716        DEBUGLOG(4, "Working on new block. Blocksize: %zu", blockSize);
   4717
   4718        additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize);
   4719        FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
   4720        blockSize -= additionalByteAdjustment;
   4721
   4722        /* If blocks are too small, emit as a nocompress block */
   4723        if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
   4724            cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
   4725            FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
   4726            DEBUGLOG(4, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize);
   4727            cSize += cBlockSize;
   4728            ip += blockSize;
   4729            op += cBlockSize;
   4730            remaining -= blockSize;
   4731            dstCapacity -= cBlockSize;
   4732            continue;
   4733        }
   4734
   4735        compressedSeqsSize = ZSTD_entropyCompressSequences(&cctx->seqStore,
   4736                                &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,
   4737                                &cctx->appliedParams,
   4738                                op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,
   4739                                blockSize,
   4740                                cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
   4741                                cctx->bmi2);
   4742        FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed");
   4743        DEBUGLOG(4, "Compressed sequences size: %zu", compressedSeqsSize);
   4744
   4745        if (!cctx->isFirstBlock &&
   4746            ZSTD_maybeRLE(&cctx->seqStore) &&
   4747            ZSTD_isRLE((BYTE const*)src, srcSize)) {
   4748            /* We don't want to emit our first block as a RLE even if it qualifies because
   4749            * doing so will cause the decoder (cli only) to throw a "should consume all input error."
   4750            * This is only an issue for zstd <= v1.4.3
   4751            */
   4752            compressedSeqsSize = 1;
   4753        }
   4754
   4755        if (compressedSeqsSize == 0) {
   4756            /* ZSTD_noCompressBlock writes the block header as well */
   4757            cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
   4758            FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
   4759            DEBUGLOG(4, "Writing out nocompress block, size: %zu", cBlockSize);
   4760        } else if (compressedSeqsSize == 1) {
   4761            cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock);
   4762            FORWARD_IF_ERROR(cBlockSize, "RLE compress block failed");
   4763            DEBUGLOG(4, "Writing out RLE block, size: %zu", cBlockSize);
   4764        } else {
   4765            U32 cBlockHeader;
   4766            /* Error checking and repcodes update */
   4767            ZSTD_confirmRepcodesAndEntropyTables(cctx);
   4768            if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
   4769                cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
   4770
   4771            /* Write block header into beginning of block*/
   4772            cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);
   4773            MEM_writeLE24(op, cBlockHeader);
   4774            cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;
   4775            DEBUGLOG(4, "Writing out compressed block, size: %zu", cBlockSize);
   4776        }
   4777
   4778        cSize += cBlockSize;
   4779        DEBUGLOG(4, "cSize running total: %zu", cSize);
   4780
   4781        if (lastBlock) {
   4782            break;
   4783        } else {
   4784            ip += blockSize;
   4785            op += cBlockSize;
   4786            remaining -= blockSize;
   4787            dstCapacity -= cBlockSize;
   4788            cctx->isFirstBlock = 0;
   4789        }
   4790    }
   4791
   4792    return cSize;
   4793}
   4794
   4795size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity,
   4796                              const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
   4797                              const void* src, size_t srcSize) {
   4798    BYTE* op = (BYTE*)dst;
   4799    size_t cSize = 0;
   4800    size_t compressedBlocksSize = 0;
   4801    size_t frameHeaderSize = 0;
   4802
   4803    /* Transparent initialization stage, same as compressStream2() */
   4804    DEBUGLOG(3, "ZSTD_compressSequences()");
   4805    assert(cctx != NULL);
   4806    FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed");
   4807    /* Begin writing output, starting with frame header */
   4808    frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID);
   4809    op += frameHeaderSize;
   4810    dstCapacity -= frameHeaderSize;
   4811    cSize += frameHeaderSize;
   4812    if (cctx->appliedParams.fParams.checksumFlag && srcSize) {
   4813        xxh64_update(&cctx->xxhState, src, srcSize);
   4814    }
   4815    /* cSize includes block header size and compressed sequences size */
   4816    compressedBlocksSize = ZSTD_compressSequences_internal(cctx,
   4817                                                           op, dstCapacity,
   4818                                                           inSeqs, inSeqsSize,
   4819                                                           src, srcSize);
   4820    FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!");
   4821    cSize += compressedBlocksSize;
   4822    dstCapacity -= compressedBlocksSize;
   4823
   4824    if (cctx->appliedParams.fParams.checksumFlag) {
   4825        U32 const checksum = (U32) xxh64_digest(&cctx->xxhState);
   4826        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
   4827        DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum);
   4828        MEM_writeLE32((char*)dst + cSize, checksum);
   4829        cSize += 4;
   4830    }
   4831
   4832    DEBUGLOG(3, "Final compressed size: %zu", cSize);
   4833    return cSize;
   4834}
   4835
   4836/*======   Finalize   ======*/
   4837
   4838/*! ZSTD_flushStream() :
   4839 * @return : amount of data remaining to flush */
   4840size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
   4841{
   4842    ZSTD_inBuffer input = { NULL, 0, 0 };
   4843    return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush);
   4844}
   4845
   4846
   4847size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
   4848{
   4849    ZSTD_inBuffer input = { NULL, 0, 0 };
   4850    size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
   4851    FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed");
   4852    if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush;   /* minimal estimation */
   4853    /* single thread mode : attempt to calculate remaining to flush more precisely */
   4854    {   size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
   4855        size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);
   4856        size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
   4857        DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
   4858        return toFlush;
   4859    }
   4860}
   4861
   4862
   4863/*-=====  Pre-defined compression levels  =====-*/
   4864
   4865#define ZSTD_MAX_CLEVEL     22
   4866int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
   4867int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
   4868
   4869static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
   4870{   /* "default" - for any srcSize > 256 KB */
   4871    /* W,  C,  H,  S,  L, TL, strat */
   4872    { 19, 12, 13,  1,  6,  1, ZSTD_fast    },  /* base for negative levels */
   4873    { 19, 13, 14,  1,  7,  0, ZSTD_fast    },  /* level  1 */
   4874    { 20, 15, 16,  1,  6,  0, ZSTD_fast    },  /* level  2 */
   4875    { 21, 16, 17,  1,  5,  0, ZSTD_dfast   },  /* level  3 */
   4876    { 21, 18, 18,  1,  5,  0, ZSTD_dfast   },  /* level  4 */
   4877    { 21, 18, 19,  2,  5,  2, ZSTD_greedy  },  /* level  5 */
   4878    { 21, 19, 19,  3,  5,  4, ZSTD_greedy  },  /* level  6 */
   4879    { 21, 19, 19,  3,  5,  8, ZSTD_lazy    },  /* level  7 */
   4880    { 21, 19, 19,  3,  5, 16, ZSTD_lazy2   },  /* level  8 */
   4881    { 21, 19, 20,  4,  5, 16, ZSTD_lazy2   },  /* level  9 */
   4882    { 22, 20, 21,  4,  5, 16, ZSTD_lazy2   },  /* level 10 */
   4883    { 22, 21, 22,  4,  5, 16, ZSTD_lazy2   },  /* level 11 */
   4884    { 22, 21, 22,  5,  5, 16, ZSTD_lazy2   },  /* level 12 */
   4885    { 22, 21, 22,  5,  5, 32, ZSTD_btlazy2 },  /* level 13 */
   4886    { 22, 22, 23,  5,  5, 32, ZSTD_btlazy2 },  /* level 14 */
   4887    { 22, 23, 23,  6,  5, 32, ZSTD_btlazy2 },  /* level 15 */
   4888    { 22, 22, 22,  5,  5, 48, ZSTD_btopt   },  /* level 16 */
   4889    { 23, 23, 22,  5,  4, 64, ZSTD_btopt   },  /* level 17 */
   4890    { 23, 23, 22,  6,  3, 64, ZSTD_btultra },  /* level 18 */
   4891    { 23, 24, 22,  7,  3,256, ZSTD_btultra2},  /* level 19 */
   4892    { 25, 25, 23,  7,  3,256, ZSTD_btultra2},  /* level 20 */
   4893    { 26, 26, 24,  7,  3,512, ZSTD_btultra2},  /* level 21 */
   4894    { 27, 27, 25,  9,  3,999, ZSTD_btultra2},  /* level 22 */
   4895},
   4896{   /* for srcSize <= 256 KB */
   4897    /* W,  C,  H,  S,  L,  T, strat */
   4898    { 18, 12, 13,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */
   4899    { 18, 13, 14,  1,  6,  0, ZSTD_fast    },  /* level  1 */
   4900    { 18, 14, 14,  1,  5,  0, ZSTD_dfast   },  /* level  2 */
   4901    { 18, 16, 16,  1,  4,  0, ZSTD_dfast   },  /* level  3 */
   4902    { 18, 16, 17,  2,  5,  2, ZSTD_greedy  },  /* level  4.*/
   4903    { 18, 18, 18,  3,  5,  2, ZSTD_greedy  },  /* level  5.*/
   4904    { 18, 18, 19,  3,  5,  4, ZSTD_lazy    },  /* level  6.*/
   4905    { 18, 18, 19,  4,  4,  4, ZSTD_lazy    },  /* level  7 */
   4906    { 18, 18, 19,  4,  4,  8, ZSTD_lazy2   },  /* level  8 */
   4907    { 18, 18, 19,  5,  4,  8, ZSTD_lazy2   },  /* level  9 */
   4908    { 18, 18, 19,  6,  4,  8, ZSTD_lazy2   },  /* level 10 */
   4909    { 18, 18, 19,  5,  4, 12, ZSTD_btlazy2 },  /* level 11.*/
   4910    { 18, 19, 19,  7,  4, 12, ZSTD_btlazy2 },  /* level 12.*/
   4911    { 18, 18, 19,  4,  4, 16, ZSTD_btopt   },  /* level 13 */
   4912    { 18, 18, 19,  4,  3, 32, ZSTD_btopt   },  /* level 14.*/
   4913    { 18, 18, 19,  6,  3,128, ZSTD_btopt   },  /* level 15.*/
   4914    { 18, 19, 19,  6,  3,128, ZSTD_btultra },  /* level 16.*/
   4915    { 18, 19, 19,  8,  3,256, ZSTD_btultra },  /* level 17.*/
   4916    { 18, 19, 19,  6,  3,128, ZSTD_btultra2},  /* level 18.*/
   4917    { 18, 19, 19,  8,  3,256, ZSTD_btultra2},  /* level 19.*/
   4918    { 18, 19, 19, 10,  3,512, ZSTD_btultra2},  /* level 20.*/
   4919    { 18, 19, 19, 12,  3,512, ZSTD_btultra2},  /* level 21.*/
   4920    { 18, 19, 19, 13,  3,999, ZSTD_btultra2},  /* level 22.*/
   4921},
   4922{   /* for srcSize <= 128 KB */
   4923    /* W,  C,  H,  S,  L,  T, strat */
   4924    { 17, 12, 12,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */
   4925    { 17, 12, 13,  1,  6,  0, ZSTD_fast    },  /* level  1 */
   4926    { 17, 13, 15,  1,  5,  0, ZSTD_fast    },  /* level  2 */
   4927    { 17, 15, 16,  2,  5,  0, ZSTD_dfast   },  /* level  3 */
   4928    { 17, 17, 17,  2,  4,  0, ZSTD_dfast   },  /* level  4 */
   4929    { 17, 16, 17,  3,  4,  2, ZSTD_greedy  },  /* level  5 */
   4930    { 17, 17, 17,  3,  4,  4, ZSTD_lazy    },  /* level  6 */
   4931    { 17, 17, 17,  3,  4,  8, ZSTD_lazy2   },  /* level  7 */
   4932    { 17, 17, 17,  4,  4,  8, ZSTD_lazy2   },  /* level  8 */
   4933    { 17, 17, 17,  5,  4,  8, ZSTD_lazy2   },  /* level  9 */
   4934    { 17, 17, 17,  6,  4,  8, ZSTD_lazy2   },  /* level 10 */
   4935    { 17, 17, 17,  5,  4,  8, ZSTD_btlazy2 },  /* level 11 */
   4936    { 17, 18, 17,  7,  4, 12, ZSTD_btlazy2 },  /* level 12 */
   4937    { 17, 18, 17,  3,  4, 12, ZSTD_btopt   },  /* level 13.*/
   4938    { 17, 18, 17,  4,  3, 32, ZSTD_btopt   },  /* level 14.*/
   4939    { 17, 18, 17,  6,  3,256, ZSTD_btopt   },  /* level 15.*/
   4940    { 17, 18, 17,  6,  3,128, ZSTD_btultra },  /* level 16.*/
   4941    { 17, 18, 17,  8,  3,256, ZSTD_btultra },  /* level 17.*/
   4942    { 17, 18, 17, 10,  3,512, ZSTD_btultra },  /* level 18.*/
   4943    { 17, 18, 17,  5,  3,256, ZSTD_btultra2},  /* level 19.*/
   4944    { 17, 18, 17,  7,  3,512, ZSTD_btultra2},  /* level 20.*/
   4945    { 17, 18, 17,  9,  3,512, ZSTD_btultra2},  /* level 21.*/
   4946    { 17, 18, 17, 11,  3,999, ZSTD_btultra2},  /* level 22.*/
   4947},
   4948{   /* for srcSize <= 16 KB */
   4949    /* W,  C,  H,  S,  L,  T, strat */
   4950    { 14, 12, 13,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */
   4951    { 14, 14, 15,  1,  5,  0, ZSTD_fast    },  /* level  1 */
   4952    { 14, 14, 15,  1,  4,  0, ZSTD_fast    },  /* level  2 */
   4953    { 14, 14, 15,  2,  4,  0, ZSTD_dfast   },  /* level  3 */
   4954    { 14, 14, 14,  4,  4,  2, ZSTD_greedy  },  /* level  4 */
   4955    { 14, 14, 14,  3,  4,  4, ZSTD_lazy    },  /* level  5.*/
   4956    { 14, 14, 14,  4,  4,  8, ZSTD_lazy2   },  /* level  6 */
   4957    { 14, 14, 14,  6,  4,  8, ZSTD_lazy2   },  /* level  7 */
   4958    { 14, 14, 14,  8,  4,  8, ZSTD_lazy2   },  /* level  8.*/
   4959    { 14, 15, 14,  5,  4,  8, ZSTD_btlazy2 },  /* level  9.*/
   4960    { 14, 15, 14,  9,  4,  8, ZSTD_btlazy2 },  /* level 10.*/
   4961    { 14, 15, 14,  3,  4, 12, ZSTD_btopt   },  /* level 11.*/
   4962    { 14, 15, 14,  4,  3, 24, ZSTD_btopt   },  /* level 12.*/
   4963    { 14, 15, 14,  5,  3, 32, ZSTD_btultra },  /* level 13.*/
   4964    { 14, 15, 15,  6,  3, 64, ZSTD_btultra },  /* level 14.*/
   4965    { 14, 15, 15,  7,  3,256, ZSTD_btultra },  /* level 15.*/
   4966    { 14, 15, 15,  5,  3, 48, ZSTD_btultra2},  /* level 16.*/
   4967    { 14, 15, 15,  6,  3,128, ZSTD_btultra2},  /* level 17.*/
   4968    { 14, 15, 15,  7,  3,256, ZSTD_btultra2},  /* level 18.*/
   4969    { 14, 15, 15,  8,  3,256, ZSTD_btultra2},  /* level 19.*/
   4970    { 14, 15, 15,  8,  3,512, ZSTD_btultra2},  /* level 20.*/
   4971    { 14, 15, 15,  9,  3,512, ZSTD_btultra2},  /* level 21.*/
   4972    { 14, 15, 15, 10,  3,999, ZSTD_btultra2},  /* level 22.*/
   4973},
   4974};
   4975
   4976static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)
   4977{
   4978    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);
   4979    switch (cParams.strategy) {
   4980        case ZSTD_fast:
   4981        case ZSTD_dfast:
   4982            break;
   4983        case ZSTD_greedy:
   4984        case ZSTD_lazy:
   4985        case ZSTD_lazy2:
   4986            cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG;
   4987            break;
   4988        case ZSTD_btlazy2:
   4989        case ZSTD_btopt:
   4990        case ZSTD_btultra:
   4991        case ZSTD_btultra2:
   4992            break;
   4993    }
   4994    return cParams;
   4995}
   4996
   4997static int ZSTD_dedicatedDictSearch_isSupported(
   4998        ZSTD_compressionParameters const* cParams)
   4999{
   5000    return (cParams->strategy >= ZSTD_greedy)
   5001        && (cParams->strategy <= ZSTD_lazy2)
   5002        && (cParams->hashLog >= cParams->chainLog)
   5003        && (cParams->chainLog <= 24);
   5004}
   5005
   5006/*
   5007 * Reverses the adjustment applied to cparams when enabling dedicated dict
   5008 * search. This is used to recover the params set to be used in the working
   5009 * context. (Otherwise, those tables would also grow.)
   5010 */
   5011static void ZSTD_dedicatedDictSearch_revertCParams(
   5012        ZSTD_compressionParameters* cParams) {
   5013    switch (cParams->strategy) {
   5014        case ZSTD_fast:
   5015        case ZSTD_dfast:
   5016            break;
   5017        case ZSTD_greedy:
   5018        case ZSTD_lazy:
   5019        case ZSTD_lazy2:
   5020            cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG;
   5021            break;
   5022        case ZSTD_btlazy2:
   5023        case ZSTD_btopt:
   5024        case ZSTD_btultra:
   5025        case ZSTD_btultra2:
   5026            break;
   5027    }
   5028}
   5029
   5030static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
   5031{
   5032    switch (mode) {
   5033    case ZSTD_cpm_unknown:
   5034    case ZSTD_cpm_noAttachDict:
   5035    case ZSTD_cpm_createCDict:
   5036        break;
   5037    case ZSTD_cpm_attachDict:
   5038        dictSize = 0;
   5039        break;
   5040    default:
   5041        assert(0);
   5042        break;
   5043    }
   5044    {   int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
   5045        size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
   5046        return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
   5047    }
   5048}
   5049
   5050/*! ZSTD_getCParams_internal() :
   5051 * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
   5052 *  Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.
   5053 *        Use dictSize == 0 for unknown or unused.
   5054 *  Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */
   5055static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
   5056{
   5057    U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);
   5058    U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
   5059    int row;
   5060    DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
   5061
   5062    /* row */
   5063    if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT;   /* 0 == default */
   5064    else if (compressionLevel < 0) row = 0;   /* entry 0 is baseline for fast mode */
   5065    else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
   5066    else row = compressionLevel;
   5067
   5068    {   ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
   5069        /* acceleration factor */
   5070        if (compressionLevel < 0) {
   5071            int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel);
   5072            cp.targetLength = (unsigned)(-clampedCompressionLevel);
   5073        }
   5074        /* refine parameters based on srcSize & dictSize */
   5075        return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode);
   5076    }
   5077}
   5078
   5079/*! ZSTD_getCParams() :
   5080 * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
   5081 *  Size values are optional, provide 0 if not known or unused */
   5082ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
   5083{
   5084    if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
   5085    return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
   5086}
   5087
   5088/*! ZSTD_getParams() :
   5089 *  same idea as ZSTD_getCParams()
   5090 * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
   5091 *  Fields of `ZSTD_frameParameters` are set to default values */
   5092static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) {
   5093    ZSTD_parameters params;
   5094    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);
   5095    DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
   5096    ZSTD_memset(&params, 0, sizeof(params));
   5097    params.cParams = cParams;
   5098    params.fParams.contentSizeFlag = 1;
   5099    return params;
   5100}
   5101
   5102/*! ZSTD_getParams() :
   5103 *  same idea as ZSTD_getCParams()
   5104 * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
   5105 *  Fields of `ZSTD_frameParameters` are set to default values */
   5106ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
   5107    if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
   5108    return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
   5109}