ReactOS  0.4.15-dev-5126-g3bb451b
zstd_compress.c
Go to the documentation of this file.
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 "cpu.h"
17 #include "mem.h"
18 #include "hist.h" /* HIST_countFast_wksp */
19 #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
20 #include "fse.h"
21 #define HUF_STATIC_LINKING_ONLY
22 #include "huf.h"
23 #include "zstd_compress_internal.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"
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  */
44 size_t ZSTD_compressBound(size_t srcSize) {
45  return ZSTD_COMPRESSBOUND(srcSize);
46 }
47 
48 
49 /*-*************************************
50 * Context memory management
51 ***************************************/
52 struct ZSTD_CDict_s {
53  const void* dictContent;
55  U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
59  ZSTD_customMem customMem;
61  int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
62 }; /* typedef'd to ZSTD_CDict within "zstd.h" */
63 
65 {
66  return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
67 }
68 
69 static 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);
77  (void)err;
78  }
79 }
80 
81 ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
82 {
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 
93 ZSTD_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) */
113  cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
114  return cctx;
115 }
116 
120 static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
121 {
122  ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
124  memset(&cctx->localDict, 0, sizeof(cctx->localDict));
125  memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
126  cctx->cdict = NULL;
127 }
128 
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 
136 static 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 
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 
163 static 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 
174 size_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)
181  + ZSTD_sizeof_mtctx(cctx);
182 }
183 
185 {
186  return ZSTD_sizeof_CCtx(zcs); /* same object */
187 }
188 
189 /* private API call, for dictBuilder only */
190 const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
191 
192 static 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 
204 static 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 
218 ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
219 {
220  return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);
221 }
222 
223 size_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 
230 size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
231 {
233 }
234 
235 size_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 
243 size_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 */
257 static 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 
269 {
270  ZSTD_bounds bounds = { 0, 0, 0 };
271 
272  switch(param)
273  {
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 
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 
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 
373  bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;
374  bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;
375  return bounds;
376 
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  */
430 static 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 
446 {
447  switch(param)
448  {
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:
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:
469  case ZSTD_c_ldmHashLog:
470  case ZSTD_c_ldmMinMatch:
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 
483 {
484  DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value);
485  if (cctx->streamStage != zcss_init) {
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 
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:
508  case ZSTD_c_format:
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:
519  case ZSTD_c_ldmHashLog:
520  case ZSTD_c_ldmMinMatch:
522  case ZSTD_c_targetCBlockSize:
523  case ZSTD_c_srcSizeHint:
524  break;
525 
526  default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
527  }
529 }
530 
531 size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
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 : {
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 */
554  CCtxParams->cParams.windowLog = (U32)value;
555  return CCtxParams->cParams.windowLog;
556 
557  case ZSTD_c_hashLog :
558  if (value!=0) /* 0 => use default */
560  CCtxParams->cParams.hashLog = (U32)value;
561  return CCtxParams->cParams.hashLog;
562 
563  case ZSTD_c_chainLog :
564  if (value!=0) /* 0 => use default */
566  CCtxParams->cParams.chainLog = (U32)value;
567  return CCtxParams->cParams.chainLog;
568 
569  case ZSTD_c_searchLog :
570  if (value!=0) /* 0 => use default */
572  CCtxParams->cParams.searchLog = (U32)value;
573  return (size_t)value;
574 
575  case ZSTD_c_minMatch :
576  if (value!=0) /* 0 => use default */
578  CCtxParams->cParams.minMatch = value;
579  return CCtxParams->cParams.minMatch;
580 
581  case ZSTD_c_targetLength :
583  CCtxParams->cParams.targetLength = value;
584  return CCtxParams->cParams.targetLength;
585 
586  case ZSTD_c_strategy :
587  if (value!=0) /* 0 => use default */
589  CCtxParams->cParams.strategy = (ZSTD_strategy)value;
590  return (size_t)CCtxParams->cParams.strategy;
591 
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
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;
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
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
666  CCtxParams->rsyncable = value;
667  return CCtxParams->rsyncable;
668 #endif
669 
671  CCtxParams->ldmParams.enableLdm = (value!=0);
672  return CCtxParams->ldmParams.enableLdm;
673 
674  case ZSTD_c_ldmHashLog :
675  if (value!=0) /* 0 ==> auto */
677  CCtxParams->ldmParams.hashLog = value;
678  return CCtxParams->ldmParams.hashLog;
679 
680  case ZSTD_c_ldmMinMatch :
681  if (value!=0) /* 0 ==> default */
683  CCtxParams->ldmParams.minMatchLength = value;
684  return CCtxParams->ldmParams.minMatchLength;
685 
687  if (value!=0) /* 0 ==> default */
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 
715 {
717 }
718 
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;
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;
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
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;
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 
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 
844 ZSTDLIB_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 
858 static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
859 {
860  ZSTD_localDict* const dl = &cctx->localDict;
861  ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
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 
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 
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 
918  ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
919 {
921  cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
922 }
923 
924 ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
925 {
927  cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
928 }
929 
930 
931 size_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 
941 size_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 
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 
963 {
966  cctx->streamStage = zcss_init;
967  cctx->pledgedSrcSizePlusOne = 0;
968  }
969  if ( (reset == ZSTD_reset_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 
983 size_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 
998 static ZSTD_compressionParameters
999 ZSTD_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 
1020 {
1021  U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
1022  return hashLog - btScale;
1023 }
1024 
1031 static ZSTD_compressionParameters
1032 ZSTD_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 
1064 ZSTD_compressionParameters
1065 ZSTD_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 
1074 static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
1075 static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
1076 
1077 ZSTD_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 
1098 static size_t
1099 ZSTD_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))
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 
1126 size_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 =
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 
1167 size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
1168 {
1169  ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
1171 }
1172 
1173 static 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 
1179 size_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 
1190 size_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 =
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 
1206 size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
1207 {
1208  ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
1210 }
1211 
1212 static 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 
1218 size_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  */
1233 ZSTD_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 
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 
1268 static 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 
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 
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 
1312 typedef enum {
1316 
1324 typedef enum {
1328 
1334 typedef enum {
1338 
1339 typedef enum {
1343 
1344 static size_t
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);
1361  }
1362 
1363  ms->hashLog3 = hashLog3;
1364 
1366 
1367  assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */
1368 
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 */
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));
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)
1413 {
1414  return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
1415 }
1416 
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);
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 
1453 
1455  needsIndexReset = ZSTDirp_reset;
1456  }
1457 
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 
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 */
1503  RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
1505  RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
1507  RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
1508  } }
1509 
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 
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  */
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 */
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 
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;
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 
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 ! */
1594  int i;
1595  for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;
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  */
1603 static 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 
1616 static 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 
1629 static size_t
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");
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) {
1663  cctx->blockState.matchState.window.base + cdictEnd;
1665  }
1666  /* loadedDictEnd is expressed within the referential of the active context */
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 
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 
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 
1707  cdict->matchState.hashTable,
1708  hSize * sizeof(U32));
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 
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. */
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)) {
1754  cctx, cdict, *params, pledgedSrcSize, zbuff);
1755  } else {
1757  cctx, cdict, *params, pledgedSrcSize, zbuff);
1758  }
1759 }
1760 
1768 static 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);
1790  }
1791 
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 
1801  srcCCtx->blockState.matchState.hashTable,
1802  hSize * sizeof(U32));
1804  srcCCtx->blockState.matchState.chainTable,
1805  chainSize * sizeof(U32));
1807  srcCCtx->blockState.matchState.hashTable3,
1808  h3Size * sizeof(U32));
1809  }
1810 
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 
1834 size_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);
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 
1856 ZSTD_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 
1890 static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
1891 {
1892  ZSTD_reduceTable_internal(table, size, reducerValue, 0);
1893 }
1894 
1895 static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
1896 {
1897  ZSTD_reduceTable_internal(table, size, reducerValue, 1);
1898 }
1899 
1902 static 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 
1929 void 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. */
1955 static 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 */
1963 MEM_STATIC size_t
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);
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,
2045  ZSTD_defaultAllowed, strategy);
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,
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 */
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,
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,
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,
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,
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 
2150 MEM_STATIC size_t
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 */
2184 {
2185  static const ZSTD_blockCompressor blockCompressor[3][ZSTD_STRATEGY_MAX+1] = {
2186  { ZSTD_compressBlock_fast /* default for 0 */,
2196  { ZSTD_compressBlock_fast_extDict /* default for 0 */,
2206  { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */,
2216  };
2217  ZSTD_blockCompressor selectedCompressor;
2218  ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
2219 
2221  selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
2222  assert(selectedCompressor != NULL);
2223  return selectedCompressor;
2224 }
2225 
2226 static 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 
2234 {
2235  ssPtr->lit = ssPtr->litStart;
2236  ssPtr->sequences = ssPtr->sequencesStart;
2237  ssPtr->longLengthID = 0;
2238 }
2239 
2241 
2242 static 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 */
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)
2278  }
2279  if (zc->externSeqStore.pos < zc->externSeqStore.size) {
2280  assert(!zc->appliedParams.ldmParams.enableLdm);
2281  /* Updates ldmSeqStore.pos */
2282  lastLLSize =
2284  ms, &zc->seqStore,
2285  zc->blockState.nextCBlock->rep,
2286  src, srcSize);
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 */
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 
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 
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 
2365 size_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 */
2386 static 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  */
2399 static 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 
2408 {
2411  zc->blockState.nextCBlock = tmp;
2412 }
2413 
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) {
2437  return 0;
2438  }
2439 
2440  /* encode sequences and literals */
2441  cSize = ZSTD_compressSequences(&zc->seqStore,
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 
2462 out:
2463  if (!ZSTD_isError(cSize) && cSize > 1) {
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 
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) {
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 
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 
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);
2565  ZSTD_reduceIndex(ms, params, correction);
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 
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 
2605  dstSize_tooSmall,
2606  "not enough space to store compressed block");
2607  if (remaining < blockSize) blockSize = remaining;
2608 
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;
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,
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 
2657 static 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) {
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  */
2707 size_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 
2717 size_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 
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 */
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);
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 
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 
2801 size_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 
2808 size_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 
2821  ldmState_t* ls,
2822  ZSTD_cwksp* ws,
2823  ZSTD_CCtx_params const* params,
2824  const void* src, size_t srcSize,
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)
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. */
2893 static 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 
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 */
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), "");
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), "");
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  */
2989  ZSTD_matchState_t* ms,
2990  ZSTD_cwksp* ws,
2991  ZSTD_CCtx_params const* params,
2992  const void* dict, size_t dictSize,
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 
3004  assert(dictSize >= 8);
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;
3031  ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
3032  return dictID;
3033  }
3034 }
3035 
3038 static size_t
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,
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 
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");
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 
3082  const void* dict, size_t dictSize,
3083  ZSTD_dictContentType_e dictContentType,
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 */
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 ?
3108  &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
3109  cdict->dictContentSize, dictContentType, dtlm,
3110  cctx->entropyWorkspace)
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 
3123  const void* dict, size_t dictSize,
3124  ZSTD_dictContentType_e dictContentType,
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,
3138 }
3139 
3143  const void* dict, size_t dictSize,
3144  ZSTD_parameters params, unsigned long long pledgedSrcSize)
3145 {
3146  ZSTD_CCtx_params const cctxParams =
3149  dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
3150  NULL /*cdict*/,
3151  &cctxParams, pledgedSrcSize);
3152 }
3153 
3154 size_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 =
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,
3162 }
3163 
3164 size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
3165 {
3166  return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
3167 }
3168 
3169 
3173 static 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);
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);
3205  op += 4;
3206  }
3207 
3208  cctx->stage = ZSTDcs_created; /* return to "created but no init" status */
3209  return op-ostart;
3210 }
3211 
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");
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 
3238 static 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 =
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 
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");
3262  return ZSTD_compress_internal(cctx,
3263  dst, dstCapacity,
3264  src, srcSize,
3265  dict, dictSize,
3266  &params);
3267 }
3268 
3269 /* 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);
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 
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 
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 
3307 size_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 
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))
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 
3336 size_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 
3342 size_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 
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 
3372 
3373 
3374  /* Reset the state to no dictionary */
3377  &cdict->matchState,
3378  &cdict->workspace,
3379  &cParams,
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 
3404 ZSTD_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 =
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 
3436  dictBuffer, dictSize,
3437  dictLoadMethod, dictContentType,
3438  cParams) )) {
3439  ZSTD_freeCDict(cdict);
3440  return NULL;
3441  }
3442 
3443  return cdict;
3444  }
3445 }
3446 
3447 ZSTD_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 
3458 ZSTD_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 
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 
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*))))
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 
3522  dict, dictSize,
3523  dictLoadMethod, dictContentType,
3524  cParams) ))
3525  return NULL;
3526 
3527  return cdict;
3528 }
3529 
3530 ZSTD_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 */
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) ?
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,
3569  }
3570 }
3571 
3572 /* ZSTD_compressBegin_usingCDict() :
3573  * pledgedSrcSize=0 means "unknown"
3574  * if pledgedSrcSize>0, it will enable contentSizeFlag */
3576 {
3577  ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
3578  DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
3580 }
3581 
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 
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 
3612 {
3613  DEBUGLOG(3, "ZSTD_createCStream");
3614  return ZSTD_createCStream_advanced(ZSTD_defaultCMem);
3615 }
3616 
3617 ZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize)
3618 {
3619  return ZSTD_initStaticCCtx(workspace, workspaceSize);
3620 }
3621 
3622 ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
3623 { /* CStream and CCtx are now same object */
3624  return ZSTD_createCCtx_advanced(customMem);
3625 }
3626 
3628 {
3629  return ZSTD_freeCCtx(zcs); /* same object */
3630 }
3631 
3632 
3633 
3634 /*====== Initialization ======*/
3635 
3636 size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX; }
3637 
3639 {
3640  return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
3641 }
3642 
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 */
3653  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3654 
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" */
3673 size_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);
3682  FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3683  return 0;
3684 }
3685 
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");
3697  FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
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 */
3713  const ZSTD_CDict* cdict,
3714  ZSTD_frameParameters fParams,
3715  unsigned long long pledgedSrcSize)
3716 {
3717  DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
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 */
3727 {
3728  DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
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. */
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");
3750  FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
3751  FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
3753  FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
3754  return 0;
3755 }
3756 
3757 size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3758 {
3759  DEBUGLOG(4, "ZSTD_initCStream_usingDict");
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 
3766 size_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");
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 
3781 size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3782 {
3783  DEBUGLOG(4, "ZSTD_initCStream");
3786  FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
3787  return 0;
3788 }
3789 
3790 /*====== Compression ======*/
3791 
3792 static 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 
3804  ZSTD_outBuffer* output,
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;
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;
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;
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 
3944 static 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 
3957 {
3959  return ZSTD_nextInputSizeHint_MTorST(zcs);
3960 }
3961 
3962 
3964  ZSTD_outBuffer* output,
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 */
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
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 */
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 
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 
4065  void* dst, size_t dstCapacity,
4066  const void* src, size_t srcSize)
4067 {
4068  DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
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 
4091 {
4092  ZSTD_inBuffer input = { NULL, 0, 0 };
4093  return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush);
4094 }
4095 
4096 
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
4116 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
4117 int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
4118 
4119 static 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 
4230 static 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 
4251 ZSTD_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 
4261 static 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 
4275 ZSTD_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 }
FORCE_INLINE_TEMPLATE void ZSTD_reduceTable_internal(U32 *const table, U32 const size, U32 const reducerValue, int const preserveMark)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
size_t ZSTD_initCStream_srcSize(ZSTD_CStream *zcs, int compressionLevel, unsigned long long pss)
#define WILDCOPY_OVERLENGTH
static size_t ZSTD_compress_internal(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize, const ZSTD_parameters *params)
#define CLAMP(cParam, val)
static int ZSTD_isRLE(const BYTE *ip, size_t length)
unsigned long long consumedSrcSize