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