zstd-ruby 1.2.0.0 → 1.3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/Makefile +7 -5
  4. data/ext/zstdruby/libzstd/common/bitstream.h +23 -9
  5. data/ext/zstdruby/libzstd/common/error_private.c +4 -1
  6. data/ext/zstdruby/libzstd/common/huf.h +20 -0
  7. data/ext/zstdruby/libzstd/common/mem.h +0 -14
  8. data/ext/zstdruby/libzstd/common/pool.c +12 -0
  9. data/ext/zstdruby/libzstd/common/pool.h +5 -0
  10. data/ext/zstdruby/libzstd/common/threading.c +0 -1
  11. data/ext/zstdruby/libzstd/common/zstd_common.c +25 -18
  12. data/ext/zstdruby/libzstd/common/zstd_errors.h +15 -7
  13. data/ext/zstdruby/libzstd/common/zstd_internal.h +59 -9
  14. data/ext/zstdruby/libzstd/compress/huf_compress.c +7 -3
  15. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1082 -487
  16. data/ext/zstdruby/libzstd/compress/zstd_opt.h +30 -15
  17. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +362 -158
  18. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +49 -13
  19. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +150 -26
  20. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +380 -258
  21. data/ext/zstdruby/libzstd/dictBuilder/cover.c +23 -37
  22. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +30 -40
  23. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +104 -95
  24. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +11 -10
  25. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +14 -19
  26. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +13 -12
  27. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +13 -14
  28. data/ext/zstdruby/libzstd/zstd.h +507 -166
  29. data/lib/zstd-ruby/version.rb +1 -1
  30. metadata +2 -2
@@ -266,7 +266,8 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
266
266
  if (highTotal <= lowTotal) break;
267
267
  } }
268
268
  /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
269
- while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
269
+ /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
270
+ while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))
270
271
  nBitsToDecrease ++;
271
272
  totalCost -= 1 << (nBitsToDecrease-1);
272
273
  if (rankLast[nBitsToDecrease-1] == noSymbol)
@@ -463,12 +464,15 @@ size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, si
463
464
  {
464
465
  case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable);
465
466
  HUF_FLUSHBITS_2(&bitC);
467
+ /* fall-through */
466
468
  case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable);
467
469
  HUF_FLUSHBITS_1(&bitC);
470
+ /* fall-through */
468
471
  case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable);
469
472
  HUF_FLUSHBITS(&bitC);
470
- case 0 :
471
- default: ;
473
+ /* fall-through */
474
+ case 0 : /* fall-through */
475
+ default: break;
472
476
  }
473
477
 
474
478
  for (; n>0; n-=4) { /* note : n&3==0 at this stage */
@@ -8,6 +8,14 @@
8
8
  */
9
9
 
10
10
 
11
+ /*-*************************************
12
+ * Tuning parameters
13
+ ***************************************/
14
+ #ifndef ZSTD_CLEVEL_DEFAULT
15
+ # define ZSTD_CLEVEL_DEFAULT 3
16
+ #endif
17
+
18
+
11
19
  /*-*************************************
12
20
  * Dependencies
13
21
  ***************************************/
@@ -18,26 +26,7 @@
18
26
  #define HUF_STATIC_LINKING_ONLY
19
27
  #include "huf.h"
20
28
  #include "zstd_internal.h" /* includes zstd.h */
21
-
22
-
23
- /*-*************************************
24
- * Debug
25
- ***************************************/
26
- #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
27
- # include <assert.h>
28
- #else
29
- # define assert(condition) ((void)0)
30
- #endif
31
-
32
- #define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
33
-
34
- #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
35
- # include <stdio.h>
36
- static unsigned g_debugLevel = ZSTD_DEBUG;
37
- # define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
38
- #else
39
- # define DEBUGLOG(l, ...) {} /* disabled */
40
- #endif
29
+ #include "zstdmt_compress.h"
41
30
 
42
31
 
43
32
  /*-*************************************
@@ -79,6 +68,15 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
79
68
  /*-*************************************
80
69
  * Context memory management
81
70
  ***************************************/
71
+ typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
72
+
73
+ struct ZSTD_CDict_s {
74
+ void* dictBuffer;
75
+ const void* dictContent;
76
+ size_t dictContentSize;
77
+ ZSTD_CCtx* refContext;
78
+ }; /* typedef'd to ZSTD_CDict within "zstd.h" */
79
+
82
80
  struct ZSTD_CCtx_s {
83
81
  const BYTE* nextSrc; /* next block here to continue on current prefix */
84
82
  const BYTE* base; /* All regular indexes relative to this position */
@@ -90,19 +88,21 @@ struct ZSTD_CCtx_s {
90
88
  U32 hashLog3; /* dispatch table : larger == faster, more memory */
91
89
  U32 loadedDictEnd; /* index of end of dictionary */
92
90
  U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
93
- U32 forceRawDict; /* Force loading dictionary in "content-only" mode (no header analysis) */
94
91
  ZSTD_compressionStage_e stage;
95
92
  U32 rep[ZSTD_REP_NUM];
96
93
  U32 repToConfirm[ZSTD_REP_NUM];
97
94
  U32 dictID;
98
- ZSTD_parameters params;
95
+ int compressionLevel;
96
+ ZSTD_parameters requestedParams;
97
+ ZSTD_parameters appliedParams;
99
98
  void* workSpace;
100
99
  size_t workSpaceSize;
101
100
  size_t blockSize;
102
- U64 frameContentSize;
101
+ U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
103
102
  U64 consumedSrcSize;
104
103
  XXH64_state_t xxhState;
105
104
  ZSTD_customMem customMem;
105
+ size_t staticSize;
106
106
 
107
107
  seqStore_t seqStore; /* sequences storage ptrs */
108
108
  U32* hashTable;
@@ -115,31 +115,92 @@ struct ZSTD_CCtx_s {
115
115
  FSE_CTable* matchlengthCTable;
116
116
  FSE_CTable* litlengthCTable;
117
117
  unsigned* entropyScratchSpace;
118
+
119
+ /* streaming */
120
+ char* inBuff;
121
+ size_t inBuffSize;
122
+ size_t inToCompress;
123
+ size_t inBuffPos;
124
+ size_t inBuffTarget;
125
+ char* outBuff;
126
+ size_t outBuffSize;
127
+ size_t outBuffContentSize;
128
+ size_t outBuffFlushedSize;
129
+ ZSTD_cStreamStage streamStage;
130
+ U32 frameEnded;
131
+
132
+ /* Dictionary */
133
+ ZSTD_dictMode_e dictMode; /* select restricting dictionary to "rawContent" or "fullDict" only */
134
+ U32 dictContentByRef;
135
+ ZSTD_CDict* cdictLocal;
136
+ const ZSTD_CDict* cdict;
137
+ const void* prefix;
138
+ size_t prefixSize;
139
+
140
+ /* Multi-threading */
141
+ U32 nbThreads;
142
+ ZSTDMT_CCtx* mtctx;
118
143
  };
119
144
 
145
+
120
146
  ZSTD_CCtx* ZSTD_createCCtx(void)
121
147
  {
122
- return ZSTD_createCCtx_advanced(defaultCustomMem);
148
+ return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
123
149
  }
124
150
 
125
151
  ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
126
152
  {
127
153
  ZSTD_CCtx* cctx;
128
154
 
129
- if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
130
- if (!customMem.customAlloc || !customMem.customFree) return NULL;
155
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
131
156
 
132
- cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
157
+ cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
133
158
  if (!cctx) return NULL;
134
- memset(cctx, 0, sizeof(ZSTD_CCtx));
135
159
  cctx->customMem = customMem;
160
+ cctx->compressionLevel = ZSTD_CLEVEL_DEFAULT;
161
+ ZSTD_STATIC_ASSERT(zcss_init==0);
162
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
163
+ return cctx;
164
+ }
165
+
166
+ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
167
+ {
168
+ ZSTD_CCtx* cctx = (ZSTD_CCtx*) workspace;
169
+ if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
170
+ if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
171
+ memset(workspace, 0, workspaceSize); /* may be a bit generous, could memset be smaller ? */
172
+ cctx->staticSize = workspaceSize;
173
+ cctx->workSpace = (void*)(cctx+1);
174
+ cctx->workSpaceSize = workspaceSize - sizeof(ZSTD_CCtx);
175
+
176
+ /* entropy space (never moves) */
177
+ /* note : this code should be shared with resetCCtx, rather than copy/pasted */
178
+ { void* ptr = cctx->workSpace;
179
+ cctx->hufCTable = (HUF_CElt*)ptr;
180
+ ptr = (char*)cctx->hufCTable + hufCTable_size;
181
+ cctx->offcodeCTable = (FSE_CTable*) ptr;
182
+ ptr = (char*)ptr + offcodeCTable_size;
183
+ cctx->matchlengthCTable = (FSE_CTable*) ptr;
184
+ ptr = (char*)ptr + matchlengthCTable_size;
185
+ cctx->litlengthCTable = (FSE_CTable*) ptr;
186
+ ptr = (char*)ptr + litlengthCTable_size;
187
+ assert(((size_t)ptr & 3) == 0); /* ensure correct alignment */
188
+ cctx->entropyScratchSpace = (unsigned*) ptr;
189
+ }
190
+
136
191
  return cctx;
137
192
  }
138
193
 
139
194
  size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
140
195
  {
141
196
  if (cctx==NULL) return 0; /* support free on NULL */
197
+ if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
142
198
  ZSTD_free(cctx->workSpace, cctx->customMem);
199
+ cctx->workSpace = NULL;
200
+ ZSTD_freeCDict(cctx->cdictLocal);
201
+ cctx->cdictLocal = NULL;
202
+ ZSTDMT_freeCCtx(cctx->mtctx);
203
+ cctx->mtctx = NULL;
143
204
  ZSTD_free(cctx, cctx->customMem);
144
205
  return 0; /* reserved as a potential error code in the future */
145
206
  }
@@ -147,46 +208,294 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
147
208
  size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
148
209
  {
149
210
  if (cctx==NULL) return 0; /* support sizeof on NULL */
150
- return sizeof(*cctx) + cctx->workSpaceSize;
211
+ DEBUGLOG(5, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
212
+ DEBUGLOG(5, "workSpaceSize : %u", (U32)cctx->workSpaceSize);
213
+ DEBUGLOG(5, "streaming buffers : %u", (U32)(cctx->outBuffSize + cctx->inBuffSize));
214
+ DEBUGLOG(5, "inner MTCTX : %u", (U32)ZSTDMT_sizeof_CCtx(cctx->mtctx));
215
+ return sizeof(*cctx) + cctx->workSpaceSize
216
+ + ZSTD_sizeof_CDict(cctx->cdictLocal)
217
+ + cctx->outBuffSize + cctx->inBuffSize
218
+ + ZSTDMT_sizeof_CCtx(cctx->mtctx);
151
219
  }
152
220
 
221
+ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
222
+ {
223
+ return ZSTD_sizeof_CCtx(zcs); /* same object */
224
+ }
225
+
226
+ /* private API call, for dictBuilder only */
227
+ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
228
+
229
+ static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx* cctx) { return cctx->appliedParams; }
230
+
231
+ /* older variant; will be deprecated */
153
232
  size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
154
233
  {
155
234
  switch(param)
156
235
  {
157
236
  case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
158
- case ZSTD_p_forceRawDict : cctx->forceRawDict = value>0; return 0;
237
+ ZSTD_STATIC_ASSERT(ZSTD_dm_auto==0);
238
+ ZSTD_STATIC_ASSERT(ZSTD_dm_rawContent==1);
239
+ case ZSTD_p_forceRawDict : cctx->dictMode = (ZSTD_dictMode_e)(value>0); return 0;
159
240
  default: return ERROR(parameter_unknown);
160
241
  }
161
242
  }
162
243
 
163
- const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
244
+
245
+ #define ZSTD_CLEVEL_CUSTOM 999
246
+ static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
164
247
  {
165
- return &(ctx->seqStore);
248
+ if (cctx->compressionLevel==ZSTD_CLEVEL_CUSTOM) return;
249
+ cctx->requestedParams.cParams = ZSTD_getCParams(cctx->compressionLevel,
250
+ cctx->pledgedSrcSizePlusOne-1, 0);
251
+ cctx->compressionLevel = ZSTD_CLEVEL_CUSTOM;
166
252
  }
167
253
 
168
- static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx* cctx)
254
+ #define CLAMPCHECK(val,min,max) { \
255
+ if (((val)<(min)) | ((val)>(max))) { \
256
+ return ERROR(compressionParameter_outOfBound); \
257
+ } }
258
+
259
+ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value)
169
260
  {
170
- return cctx->params;
261
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
262
+
263
+ switch(param)
264
+ {
265
+ case ZSTD_p_compressionLevel :
266
+ if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel(); /* cap max compression level */
267
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
268
+ if (cctx->cdict) return ERROR(stage_wrong);
269
+ cctx->compressionLevel = value;
270
+ return 0;
271
+
272
+ case ZSTD_p_windowLog :
273
+ DEBUGLOG(5, "setting ZSTD_p_windowLog = %u (cdict:%u)",
274
+ value, (cctx->cdict!=NULL));
275
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
276
+ if (cctx->cdict) return ERROR(stage_wrong);
277
+ CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
278
+ ZSTD_cLevelToCParams(cctx);
279
+ cctx->requestedParams.cParams.windowLog = value;
280
+ return 0;
281
+
282
+ case ZSTD_p_hashLog :
283
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
284
+ if (cctx->cdict) return ERROR(stage_wrong);
285
+ CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
286
+ ZSTD_cLevelToCParams(cctx);
287
+ cctx->requestedParams.cParams.hashLog = value;
288
+ return 0;
289
+
290
+ case ZSTD_p_chainLog :
291
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
292
+ if (cctx->cdict) return ERROR(stage_wrong);
293
+ CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
294
+ ZSTD_cLevelToCParams(cctx);
295
+ cctx->requestedParams.cParams.chainLog = value;
296
+ return 0;
297
+
298
+ case ZSTD_p_searchLog :
299
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
300
+ if (cctx->cdict) return ERROR(stage_wrong);
301
+ CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
302
+ ZSTD_cLevelToCParams(cctx);
303
+ cctx->requestedParams.cParams.searchLog = value;
304
+ return 0;
305
+
306
+ case ZSTD_p_minMatch :
307
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
308
+ if (cctx->cdict) return ERROR(stage_wrong);
309
+ CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
310
+ ZSTD_cLevelToCParams(cctx);
311
+ cctx->requestedParams.cParams.searchLength = value;
312
+ return 0;
313
+
314
+ case ZSTD_p_targetLength :
315
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
316
+ if (cctx->cdict) return ERROR(stage_wrong);
317
+ CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
318
+ ZSTD_cLevelToCParams(cctx);
319
+ cctx->requestedParams.cParams.targetLength = value;
320
+ return 0;
321
+
322
+ case ZSTD_p_compressionStrategy :
323
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
324
+ if (cctx->cdict) return ERROR(stage_wrong);
325
+ CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
326
+ ZSTD_cLevelToCParams(cctx);
327
+ cctx->requestedParams.cParams.strategy = (ZSTD_strategy)value;
328
+ return 0;
329
+
330
+ case ZSTD_p_contentSizeFlag :
331
+ DEBUGLOG(5, "set content size flag = %u", (value>0));
332
+ /* Content size written in frame header _when known_ (default:1) */
333
+ cctx->requestedParams.fParams.contentSizeFlag = value>0;
334
+ return 0;
335
+
336
+ case ZSTD_p_checksumFlag :
337
+ /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
338
+ cctx->requestedParams.fParams.checksumFlag = value>0;
339
+ return 0;
340
+
341
+ case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
342
+ DEBUGLOG(5, "set dictIDFlag = %u", (value>0));
343
+ cctx->requestedParams.fParams.noDictIDFlag = (value==0);
344
+ return 0;
345
+
346
+ /* Dictionary parameters */
347
+ case ZSTD_p_dictMode :
348
+ if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
349
+ /* restrict dictionary mode, to "rawContent" or "fullDict" only */
350
+ ZSTD_STATIC_ASSERT((U32)ZSTD_dm_fullDict > (U32)ZSTD_dm_rawContent);
351
+ if (value > (unsigned)ZSTD_dm_fullDict)
352
+ return ERROR(compressionParameter_outOfBound);
353
+ cctx->dictMode = (ZSTD_dictMode_e)value;
354
+ return 0;
355
+
356
+ case ZSTD_p_refDictContent :
357
+ if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
358
+ /* dictionary content will be referenced, instead of copied */
359
+ cctx->dictContentByRef = value>0;
360
+ return 0;
361
+
362
+ case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
363
+ * even when referencing into Dictionary content
364
+ * default : 0 when using a CDict, 1 when using a Prefix */
365
+ cctx->forceWindow = value>0;
366
+ cctx->loadedDictEnd = 0;
367
+ return 0;
368
+
369
+ case ZSTD_p_nbThreads:
370
+ if (value==0) return 0;
371
+ DEBUGLOG(5, " setting nbThreads : %u", value);
372
+ #ifndef ZSTD_MULTITHREAD
373
+ if (value > 1) return ERROR(compressionParameter_unsupported);
374
+ #endif
375
+ if ((value>1) && (cctx->nbThreads != value)) {
376
+ if (cctx->staticSize) /* MT not compatible with static alloc */
377
+ return ERROR(compressionParameter_unsupported);
378
+ ZSTDMT_freeCCtx(cctx->mtctx);
379
+ cctx->nbThreads = 1;
380
+ cctx->mtctx = ZSTDMT_createCCtx(value);
381
+ if (cctx->mtctx == NULL) return ERROR(memory_allocation);
382
+ }
383
+ cctx->nbThreads = value;
384
+ return 0;
385
+
386
+ case ZSTD_p_jobSize:
387
+ if (cctx->nbThreads <= 1) return ERROR(compressionParameter_unsupported);
388
+ assert(cctx->mtctx != NULL);
389
+ return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_sectionSize, value);
390
+
391
+ case ZSTD_p_overlapSizeLog:
392
+ DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->nbThreads);
393
+ if (cctx->nbThreads <= 1) return ERROR(compressionParameter_unsupported);
394
+ assert(cctx->mtctx != NULL);
395
+ return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_overlapSectionLog, value);
396
+
397
+ default: return ERROR(parameter_unknown);
398
+ }
399
+ }
400
+
401
+ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
402
+ {
403
+ DEBUGLOG(5, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
404
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
405
+ cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
406
+ return 0;
407
+ }
408
+
409
+ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
410
+ {
411
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
412
+ if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
413
+ DEBUGLOG(5, "load dictionary of size %u", (U32)dictSize);
414
+ ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
415
+ if (dict==NULL || dictSize==0) { /* no dictionary mode */
416
+ cctx->cdictLocal = NULL;
417
+ cctx->cdict = NULL;
418
+ } else {
419
+ ZSTD_compressionParameters const cParams =
420
+ cctx->compressionLevel == ZSTD_CLEVEL_CUSTOM ?
421
+ cctx->requestedParams.cParams :
422
+ ZSTD_getCParams(cctx->compressionLevel, 0, dictSize);
423
+ cctx->cdictLocal = ZSTD_createCDict_advanced(
424
+ dict, dictSize,
425
+ cctx->dictContentByRef, cctx->dictMode,
426
+ cParams, cctx->customMem);
427
+ cctx->cdict = cctx->cdictLocal;
428
+ if (cctx->cdictLocal == NULL)
429
+ return ERROR(memory_allocation);
430
+ }
431
+ return 0;
432
+ }
433
+
434
+ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
435
+ {
436
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
437
+ cctx->cdict = cdict;
438
+ cctx->prefix = NULL; /* exclusive */
439
+ cctx->prefixSize = 0;
440
+ return 0;
441
+ }
442
+
443
+ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
444
+ {
445
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
446
+ cctx->cdict = NULL; /* prefix discards any prior cdict */
447
+ cctx->prefix = prefix;
448
+ cctx->prefixSize = prefixSize;
449
+ return 0;
450
+ }
451
+
452
+ static void ZSTD_startNewCompression(ZSTD_CCtx* cctx)
453
+ {
454
+ cctx->streamStage = zcss_init;
455
+ cctx->pledgedSrcSizePlusOne = 0;
171
456
  }
172
457
 
458
+ /*! ZSTD_CCtx_reset() :
459
+ * Also dumps dictionary */
460
+ void ZSTD_CCtx_reset(ZSTD_CCtx* cctx)
461
+ {
462
+ ZSTD_startNewCompression(cctx);
463
+ cctx->cdict = NULL;
464
+ }
173
465
 
174
- /** ZSTD_checkParams() :
175
- ensure param values remain within authorized range.
466
+ /** ZSTD_checkCParams() :
467
+ control CParam values remain within authorized range.
176
468
  @return : 0, or an error code if one value is beyond authorized range */
177
469
  size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
178
470
  {
179
- # define CLAMPCHECK(val,min,max) { if ((val<min) | (val>max)) return ERROR(compressionParameter_unsupported); }
180
471
  CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
181
472
  CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
182
473
  CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
183
474
  CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
184
475
  CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
185
476
  CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
186
- if ((U32)(cParams.strategy) > (U32)ZSTD_btopt2) return ERROR(compressionParameter_unsupported);
477
+ if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) return ERROR(compressionParameter_unsupported);
187
478
  return 0;
188
479
  }
189
480
 
481
+ /** ZSTD_clampCParams() :
482
+ * make CParam values within valid range.
483
+ * @return : valid CParams */
484
+ static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters cParams)
485
+ {
486
+ # define CLAMP(val,min,max) { \
487
+ if (val<min) val=min; \
488
+ else if (val>max) val=max; \
489
+ }
490
+ CLAMP(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
491
+ CLAMP(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
492
+ CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
493
+ CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
494
+ CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
495
+ CLAMP(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
496
+ if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra;
497
+ return cParams;
498
+ }
190
499
 
191
500
  /** ZSTD_cycleLog() :
192
501
  * condition for correct operation : hashLog > 1 */
@@ -196,14 +505,15 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
196
505
  return hashLog - btScale;
197
506
  }
198
507
 
199
- /** ZSTD_adjustCParams() :
508
+ /** ZSTD_adjustCParams_internal() :
200
509
  optimize `cPar` for a given input (`srcSize` and `dictSize`).
201
510
  mostly downsizing to reduce memory consumption and initialization.
202
511
  Both `srcSize` and `dictSize` are optional (use 0 if unknown),
203
512
  but if both are 0, no optimization can be done.
204
513
  Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
205
- ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
514
+ ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
206
515
  {
516
+ assert(ZSTD_checkCParams(cPar)==0);
207
517
  if (srcSize+dictSize == 0) return cPar; /* no size information available : no adjustment */
208
518
 
209
519
  /* resize params, to use less memory when necessary */
@@ -223,10 +533,16 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
223
533
  return cPar;
224
534
  }
225
535
 
536
+ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
537
+ {
538
+ cPar = ZSTD_clampCParams(cPar);
539
+ return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
540
+ }
226
541
 
227
- size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
542
+
543
+ size_t ZSTD_estimateCCtxSize_advanced(ZSTD_compressionParameters cParams)
228
544
  {
229
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog);
545
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
230
546
  U32 const divider = (cParams.searchLength==3) ? 3 : 4;
231
547
  size_t const maxNbSeq = blockSize / divider;
232
548
  size_t const tokenSpace = blockSize + 11*maxNbSeq;
@@ -240,31 +556,64 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
240
556
  + entropyScratchSpace_size;
241
557
  size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
242
558
 
243
- size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
559
+ size_t const optBudget = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
244
560
  + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
245
- size_t const neededSpace = entropySpace + tableSpace + tokenSpace
246
- + (((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btopt2)) ? optSpace : 0);
561
+ size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
562
+ size_t const neededSpace = entropySpace + tableSpace + tokenSpace + optSpace;
247
563
 
564
+ DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
565
+ DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
248
566
  return sizeof(ZSTD_CCtx) + neededSpace;
249
567
  }
250
568
 
569
+ size_t ZSTD_estimateCCtxSize(int compressionLevel)
570
+ {
571
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
572
+ return ZSTD_estimateCCtxSize_advanced(cParams);
573
+ }
251
574
 
252
- static U32 ZSTD_equivalentParams(ZSTD_parameters param1, ZSTD_parameters param2)
575
+ size_t ZSTD_estimateCStreamSize_advanced(ZSTD_compressionParameters cParams)
253
576
  {
254
- return (param1.cParams.hashLog == param2.cParams.hashLog)
255
- & (param1.cParams.chainLog == param2.cParams.chainLog)
256
- & (param1.cParams.strategy == param2.cParams.strategy)
257
- & ((param1.cParams.searchLength==3) == (param2.cParams.searchLength==3));
577
+ size_t const CCtxSize = ZSTD_estimateCCtxSize_advanced(cParams);
578
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
579
+ size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
580
+ size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
581
+ size_t const streamingSize = inBuffSize + outBuffSize;
582
+
583
+ return CCtxSize + streamingSize;
584
+ }
585
+
586
+ size_t ZSTD_estimateCStreamSize(int compressionLevel) {
587
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
588
+ return ZSTD_estimateCStreamSize_advanced(cParams);
589
+ }
590
+
591
+
592
+ static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
593
+ ZSTD_compressionParameters cParams2)
594
+ {
595
+ U32 bslog1 = MIN(cParams1.windowLog, ZSTD_BLOCKSIZELOG_MAX);
596
+ U32 bslog2 = MIN(cParams2.windowLog, ZSTD_BLOCKSIZELOG_MAX);
597
+ return (bslog1 == bslog2) /* same block size */
598
+ & (cParams1.hashLog == cParams2.hashLog)
599
+ & (cParams1.chainLog == cParams2.chainLog)
600
+ & (cParams1.strategy == cParams2.strategy) /* opt parser space */
601
+ & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
258
602
  }
259
603
 
260
604
  /*! ZSTD_continueCCtx() :
261
- reuse CCtx without reset (note : requires no dictionary) */
262
- static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 frameContentSize)
605
+ * reuse CCtx without reset (note : requires no dictionary) */
606
+ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 pledgedSrcSize)
263
607
  {
264
608
  U32 const end = (U32)(cctx->nextSrc - cctx->base);
265
- cctx->params = params;
266
- cctx->frameContentSize = frameContentSize;
609
+ DEBUGLOG(5, "continue mode");
610
+ cctx->appliedParams = params;
611
+ cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
267
612
  cctx->consumedSrcSize = 0;
613
+ if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
614
+ cctx->appliedParams.fParams.contentSizeFlag = 0;
615
+ DEBUGLOG(5, "pledged content size : %u ; flag : %u",
616
+ (U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
268
617
  cctx->lowLimit = end;
269
618
  cctx->dictLimit = end;
270
619
  cctx->nextToUpdate = end+1;
@@ -277,30 +626,39 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 fra
277
626
  return 0;
278
627
  }
279
628
 
280
- typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset, ZSTDcrp_fullReset } ZSTD_compResetPolicy_e;
629
+ typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
630
+ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
281
631
 
282
632
  /*! ZSTD_resetCCtx_internal() :
283
- note : `params` must be validated */
284
- static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
285
- ZSTD_parameters params, U64 frameContentSize,
286
- ZSTD_compResetPolicy_e const crp)
633
+ note : `params` are assumed fully validated at this stage */
634
+ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
635
+ ZSTD_parameters params, U64 pledgedSrcSize,
636
+ ZSTD_compResetPolicy_e const crp,
637
+ ZSTD_buffered_policy_e const zbuff)
287
638
  {
288
- if (crp == ZSTDcrp_continue)
289
- if (ZSTD_equivalentParams(params, zc->params)) {
639
+ assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
640
+
641
+ if (crp == ZSTDcrp_continue) {
642
+ if (ZSTD_equivalentParams(params.cParams, zc->appliedParams.cParams)) {
643
+ DEBUGLOG(5, "ZSTD_equivalentParams()==1");
290
644
  zc->fseCTables_ready = 0;
291
645
  zc->hufCTable_repeatMode = HUF_repeat_none;
292
- return ZSTD_continueCCtx(zc, params, frameContentSize);
293
- }
646
+ return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
647
+ } }
294
648
 
295
- { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog);
649
+ { size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
296
650
  U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
297
651
  size_t const maxNbSeq = blockSize / divider;
298
652
  size_t const tokenSpace = blockSize + 11*maxNbSeq;
299
- size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
653
+ size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
654
+ 0 : (1 << params.cParams.chainLog);
300
655
  size_t const hSize = ((size_t)1) << params.cParams.hashLog;
301
- U32 const hashLog3 = (params.cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
656
+ U32 const hashLog3 = (params.cParams.searchLength>3) ?
657
+ 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
302
658
  size_t const h3Size = ((size_t)1) << hashLog3;
303
659
  size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
660
+ size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
661
+ size_t const buffInSize = (zbuff==ZSTDb_buffered) ? ((size_t)1 << params.cParams.windowLog) + blockSize : 0;
304
662
  void* ptr;
305
663
 
306
664
  /* Check if workSpace is large enough, alloc a new one if needed */
@@ -309,9 +667,20 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
309
667
  + entropyScratchSpace_size;
310
668
  size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
311
669
  + (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
312
- size_t const optSpace = ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) ? optPotentialSpace : 0;
313
- size_t const neededSpace = entropySpace + optSpace + tableSpace + tokenSpace;
314
- if (zc->workSpaceSize < neededSpace) {
670
+ size_t const optSpace = ( (params.cParams.strategy == ZSTD_btopt)
671
+ || (params.cParams.strategy == ZSTD_btultra)) ?
672
+ optPotentialSpace : 0;
673
+ size_t const bufferSpace = buffInSize + buffOutSize;
674
+ size_t const neededSpace = entropySpace + optSpace + tableSpace
675
+ + tokenSpace + bufferSpace;
676
+
677
+ if (zc->workSpaceSize < neededSpace) { /* too small : resize /*/
678
+ DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
679
+ (unsigned)zc->workSpaceSize>>10,
680
+ (unsigned)neededSpace>>10);
681
+ /* static cctx : no resize, error out */
682
+ if (zc->staticSize) return ERROR(memory_allocation);
683
+
315
684
  zc->workSpaceSize = 0;
316
685
  ZSTD_free(zc->workSpace, zc->customMem);
317
686
  zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
@@ -333,10 +702,14 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
333
702
  } }
334
703
 
335
704
  /* init params */
336
- zc->params = params;
337
- zc->blockSize = blockSize;
338
- zc->frameContentSize = frameContentSize;
705
+ zc->appliedParams = params;
706
+ zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
339
707
  zc->consumedSrcSize = 0;
708
+ if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
709
+ zc->appliedParams.fParams.contentSizeFlag = 0;
710
+ DEBUGLOG(5, "pledged content size : %u ; flag : %u",
711
+ (U32)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
712
+ zc->blockSize = blockSize;
340
713
 
341
714
  XXH64_reset(&zc->xxhState, 0);
342
715
  zc->stage = ZSTDcs_init;
@@ -363,7 +736,8 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
363
736
  ptr = (char*)zc->entropyScratchSpace + entropyScratchSpace_size;
364
737
 
365
738
  /* opt parser space */
366
- if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) {
739
+ if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) {
740
+ DEBUGLOG(5, "reserving optimal parser space");
367
741
  assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
368
742
  zc->seqStore.litFreq = (U32*)ptr;
369
743
  zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
@@ -391,6 +765,13 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
391
765
  zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
392
766
  zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
393
767
  zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
768
+ ptr = zc->seqStore.litStart + blockSize;
769
+
770
+ /* buffers */
771
+ zc->inBuffSize = buffInSize;
772
+ zc->inBuff = (char*)ptr;
773
+ zc->outBuffSize = buffOutSize;
774
+ zc->outBuff = zc->inBuff + buffInSize;
394
775
 
395
776
  return 0;
396
777
  }
@@ -411,21 +792,25 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
411
792
  * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
412
793
  * pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
413
794
  * @return : 0, or an error code */
414
- size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx,
415
- ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize)
795
+ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
796
+ const ZSTD_CCtx* srcCCtx,
797
+ ZSTD_frameParameters fParams,
798
+ unsigned long long pledgedSrcSize,
799
+ ZSTD_buffered_policy_e zbuff)
416
800
  {
801
+ DEBUGLOG(5, "ZSTD_copyCCtx_internal");
417
802
  if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
418
803
 
419
804
  memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
420
- { ZSTD_parameters params = srcCCtx->params;
805
+ { ZSTD_parameters params = srcCCtx->appliedParams;
421
806
  params.fParams = fParams;
422
- DEBUGLOG(5, "ZSTD_resetCCtx_internal : dictIDFlag : %u \n", !fParams.noDictIDFlag);
423
- ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize, ZSTDcrp_noMemset);
807
+ ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
808
+ ZSTDcrp_noMemset, zbuff);
424
809
  }
425
810
 
426
811
  /* copy tables */
427
- { size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
428
- size_t const hSize = (size_t)1 << srcCCtx->params.cParams.hashLog;
812
+ { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->appliedParams.cParams.chainLog);
813
+ size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
429
814
  size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
430
815
  size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
431
816
  assert((U32*)dstCCtx->chainTable == (U32*)dstCCtx->hashTable + hSize); /* chainTable must follow hashTable */
@@ -467,9 +852,11 @@ size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx,
467
852
  size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
468
853
  {
469
854
  ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
855
+ ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0);
856
+ ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
470
857
  fParams.contentSizeFlag = pledgedSrcSize>0;
471
858
 
472
- return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize);
859
+ return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize, zbuff);
473
860
  }
474
861
 
475
862
 
@@ -488,10 +875,10 @@ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reduce
488
875
  * rescale all indexes to avoid future overflow (indexes are U32) */
489
876
  static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
490
877
  {
491
- { U32 const hSize = 1 << zc->params.cParams.hashLog;
878
+ { U32 const hSize = 1 << zc->appliedParams.cParams.hashLog;
492
879
  ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
493
880
 
494
- { U32 const chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog);
881
+ { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->appliedParams.cParams.chainLog);
495
882
  ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
496
883
 
497
884
  { U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
@@ -529,10 +916,11 @@ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void
529
916
  case 2: /* 2 - 2 - 12 */
530
917
  MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
531
918
  break;
532
- default: /*note : should not be necessary : flSize is within {1,2,3} */
533
919
  case 3: /* 2 - 2 - 20 */
534
920
  MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
535
921
  break;
922
+ default: /* not necessary : flSize is {1,2,3} */
923
+ assert(0);
536
924
  }
537
925
 
538
926
  memcpy(ostart + flSize, src, srcSize);
@@ -554,10 +942,11 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
554
942
  case 2: /* 2 - 2 - 12 */
555
943
  MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
556
944
  break;
557
- default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */
558
945
  case 3: /* 2 - 2 - 20 */
559
946
  MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
560
947
  break;
948
+ default: /* not necessary : flSize is {1,2,3} */
949
+ assert(0);
561
950
  }
562
951
 
563
952
  ostart[flSize] = *(const BYTE*)src;
@@ -587,7 +976,7 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
587
976
 
588
977
  if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
589
978
  { HUF_repeat repeat = zc->hufCTable_repeatMode;
590
- int const preferRepeat = zc->params.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
979
+ int const preferRepeat = zc->appliedParams.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
591
980
  if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
592
981
  cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
593
982
  zc->entropyScratchSpace, entropyScratchSpace_size, zc->hufCTable, &repeat, preferRepeat)
@@ -619,13 +1008,14 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
619
1008
  MEM_writeLE32(ostart, lhc);
620
1009
  break;
621
1010
  }
622
- default: /* should not be necessary, lhSize is only {3,4,5} */
623
1011
  case 5: /* 2 - 2 - 18 - 18 */
624
1012
  { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
625
1013
  MEM_writeLE32(ostart, lhc);
626
1014
  ostart[4] = (BYTE)(cLitSize >> 10);
627
1015
  break;
628
1016
  }
1017
+ default: /* not possible : lhSize is {3,4,5} */
1018
+ assert(0);
629
1019
  }
630
1020
  return lhSize+cLitSize;
631
1021
  }
@@ -676,7 +1066,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
676
1066
  void* dst, size_t dstCapacity,
677
1067
  size_t srcSize)
678
1068
  {
679
- const int longOffsets = zc->params.cParams.windowLog > STREAM_ACCUMULATOR_MIN;
1069
+ const int longOffsets = zc->appliedParams.cParams.windowLog > STREAM_ACCUMULATOR_MIN;
680
1070
  const seqStore_t* seqStorePtr = &(zc->seqStore);
681
1071
  U32 count[MaxSeq+1];
682
1072
  S16 norm[MaxSeq+1];
@@ -881,12 +1271,6 @@ _check_compressibility:
881
1271
  return op - ostart;
882
1272
  }
883
1273
 
884
- #if 0 /* for debug */
885
- # define STORESEQ_DEBUG
886
- #include <stdio.h> /* fprintf */
887
- U32 g_startDebug = 0;
888
- const BYTE* g_start = NULL;
889
- #endif
890
1274
 
891
1275
  /*! ZSTD_storeSeq() :
892
1276
  Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
@@ -895,16 +1279,16 @@ const BYTE* g_start = NULL;
895
1279
  */
896
1280
  MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
897
1281
  {
898
- #ifdef STORESEQ_DEBUG
899
- if (g_startDebug) {
900
- const U32 pos = (U32)((const BYTE*)literals - g_start);
901
- if (g_start==NULL) g_start = (const BYTE*)literals;
902
- if ((pos > 1895000) && (pos < 1895300))
903
- DEBUGLOG(5, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
904
- pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
905
- }
1282
+ #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
1283
+ static const BYTE* g_start = NULL;
1284
+ U32 const pos = (U32)((const BYTE*)literals - g_start);
1285
+ if (g_start==NULL) g_start = (const BYTE*)literals;
1286
+ if ((pos > 0) && (pos < 1000000000))
1287
+ DEBUGLOG(6, "Cpos %6u :%5u literals & match %3u bytes at distance %6u",
1288
+ pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
906
1289
  #endif
907
1290
  /* copy Literals */
1291
+ assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
908
1292
  ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
909
1293
  seqStorePtr->lit += litLength;
910
1294
 
@@ -1078,7 +1462,7 @@ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
1078
1462
  static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
1079
1463
  {
1080
1464
  U32* const hashTable = zc->hashTable;
1081
- U32 const hBits = zc->params.cParams.hashLog;
1465
+ U32 const hBits = zc->appliedParams.cParams.hashLog;
1082
1466
  const BYTE* const base = zc->base;
1083
1467
  const BYTE* ip = base + zc->nextToUpdate;
1084
1468
  const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
@@ -1097,7 +1481,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
1097
1481
  const U32 mls)
1098
1482
  {
1099
1483
  U32* const hashTable = cctx->hashTable;
1100
- U32 const hBits = cctx->params.cParams.hashLog;
1484
+ U32 const hBits = cctx->appliedParams.cParams.hashLog;
1101
1485
  seqStore_t* seqStorePtr = &(cctx->seqStore);
1102
1486
  const BYTE* const base = cctx->base;
1103
1487
  const BYTE* const istart = (const BYTE*)src;
@@ -1182,7 +1566,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
1182
1566
  static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
1183
1567
  const void* src, size_t srcSize)
1184
1568
  {
1185
- const U32 mls = ctx->params.cParams.searchLength;
1569
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
1186
1570
  switch(mls)
1187
1571
  {
1188
1572
  default: /* includes case 3 */
@@ -1203,7 +1587,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
1203
1587
  const U32 mls)
1204
1588
  {
1205
1589
  U32* hashTable = ctx->hashTable;
1206
- const U32 hBits = ctx->params.cParams.hashLog;
1590
+ const U32 hBits = ctx->appliedParams.cParams.hashLog;
1207
1591
  seqStore_t* seqStorePtr = &(ctx->seqStore);
1208
1592
  const BYTE* const base = ctx->base;
1209
1593
  const BYTE* const dictBase = ctx->dictBase;
@@ -1296,7 +1680,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
1296
1680
  static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
1297
1681
  const void* src, size_t srcSize)
1298
1682
  {
1299
- U32 const mls = ctx->params.cParams.searchLength;
1683
+ U32 const mls = ctx->appliedParams.cParams.searchLength;
1300
1684
  switch(mls)
1301
1685
  {
1302
1686
  default: /* includes case 3 */
@@ -1318,9 +1702,9 @@ static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
1318
1702
  static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls)
1319
1703
  {
1320
1704
  U32* const hashLarge = cctx->hashTable;
1321
- U32 const hBitsL = cctx->params.cParams.hashLog;
1705
+ U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
1322
1706
  U32* const hashSmall = cctx->chainTable;
1323
- U32 const hBitsS = cctx->params.cParams.chainLog;
1707
+ U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
1324
1708
  const BYTE* const base = cctx->base;
1325
1709
  const BYTE* ip = base + cctx->nextToUpdate;
1326
1710
  const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
@@ -1340,9 +1724,9 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
1340
1724
  const U32 mls)
1341
1725
  {
1342
1726
  U32* const hashLong = cctx->hashTable;
1343
- const U32 hBitsL = cctx->params.cParams.hashLog;
1727
+ const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
1344
1728
  U32* const hashSmall = cctx->chainTable;
1345
- const U32 hBitsS = cctx->params.cParams.chainLog;
1729
+ const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
1346
1730
  seqStore_t* seqStorePtr = &(cctx->seqStore);
1347
1731
  const BYTE* const base = cctx->base;
1348
1732
  const BYTE* const istart = (const BYTE*)src;
@@ -1452,7 +1836,7 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
1452
1836
 
1453
1837
  static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1454
1838
  {
1455
- const U32 mls = ctx->params.cParams.searchLength;
1839
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
1456
1840
  switch(mls)
1457
1841
  {
1458
1842
  default: /* includes case 3 */
@@ -1473,9 +1857,9 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
1473
1857
  const U32 mls)
1474
1858
  {
1475
1859
  U32* const hashLong = ctx->hashTable;
1476
- U32 const hBitsL = ctx->params.cParams.hashLog;
1860
+ U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
1477
1861
  U32* const hashSmall = ctx->chainTable;
1478
- U32 const hBitsS = ctx->params.cParams.chainLog;
1862
+ U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
1479
1863
  seqStore_t* seqStorePtr = &(ctx->seqStore);
1480
1864
  const BYTE* const base = ctx->base;
1481
1865
  const BYTE* const dictBase = ctx->dictBase;
@@ -1602,7 +1986,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
1602
1986
  static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
1603
1987
  const void* src, size_t srcSize)
1604
1988
  {
1605
- U32 const mls = ctx->params.cParams.searchLength;
1989
+ U32 const mls = ctx->appliedParams.cParams.searchLength;
1606
1990
  switch(mls)
1607
1991
  {
1608
1992
  default: /* includes case 3 */
@@ -1628,10 +2012,10 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
1628
2012
  U32 extDict)
1629
2013
  {
1630
2014
  U32* const hashTable = zc->hashTable;
1631
- U32 const hashLog = zc->params.cParams.hashLog;
2015
+ U32 const hashLog = zc->appliedParams.cParams.hashLog;
1632
2016
  size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
1633
2017
  U32* const bt = zc->chainTable;
1634
- U32 const btLog = zc->params.cParams.chainLog - 1;
2018
+ U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
1635
2019
  U32 const btMask = (1 << btLog) - 1;
1636
2020
  U32 matchIndex = hashTable[h];
1637
2021
  size_t commonLengthSmaller=0, commonLengthLarger=0;
@@ -1733,10 +2117,10 @@ static size_t ZSTD_insertBtAndFindBestMatch (
1733
2117
  U32 extDict)
1734
2118
  {
1735
2119
  U32* const hashTable = zc->hashTable;
1736
- U32 const hashLog = zc->params.cParams.hashLog;
2120
+ U32 const hashLog = zc->appliedParams.cParams.hashLog;
1737
2121
  size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
1738
2122
  U32* const bt = zc->chainTable;
1739
- U32 const btLog = zc->params.cParams.chainLog - 1;
2123
+ U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
1740
2124
  U32 const btMask = (1 << btLog) - 1;
1741
2125
  U32 matchIndex = hashTable[h];
1742
2126
  size_t commonLengthSmaller=0, commonLengthLarger=0;
@@ -1896,9 +2280,9 @@ FORCE_INLINE
1896
2280
  U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
1897
2281
  {
1898
2282
  U32* const hashTable = zc->hashTable;
1899
- const U32 hashLog = zc->params.cParams.hashLog;
2283
+ const U32 hashLog = zc->appliedParams.cParams.hashLog;
1900
2284
  U32* const chainTable = zc->chainTable;
1901
- const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1;
2285
+ const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
1902
2286
  const BYTE* const base = zc->base;
1903
2287
  const U32 target = (U32)(ip - base);
1904
2288
  U32 idx = zc->nextToUpdate;
@@ -1915,8 +2299,8 @@ U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
1915
2299
  }
1916
2300
 
1917
2301
 
1918
-
1919
- FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
2302
+ /* inlining is important to hardwire a hot branch (template emulation) */
2303
+ FORCE_INLINE
1920
2304
  size_t ZSTD_HcFindBestMatch_generic (
1921
2305
  ZSTD_CCtx* zc, /* Index table will be updated */
1922
2306
  const BYTE* const ip, const BYTE* const iLimit,
@@ -1924,7 +2308,7 @@ size_t ZSTD_HcFindBestMatch_generic (
1924
2308
  const U32 maxNbAttempts, const U32 mls, const U32 extDict)
1925
2309
  {
1926
2310
  U32* const chainTable = zc->chainTable;
1927
- const U32 chainSize = (1 << zc->params.cParams.chainLog);
2311
+ const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
1928
2312
  const U32 chainMask = chainSize-1;
1929
2313
  const BYTE* const base = zc->base;
1930
2314
  const BYTE* const dictBase = zc->dictBase;
@@ -2018,8 +2402,8 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
2018
2402
  const BYTE* const ilimit = iend - 8;
2019
2403
  const BYTE* const base = ctx->base + ctx->dictLimit;
2020
2404
 
2021
- U32 const maxSearches = 1 << ctx->params.cParams.searchLog;
2022
- U32 const mls = ctx->params.cParams.searchLength;
2405
+ U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
2406
+ U32 const mls = ctx->appliedParams.cParams.searchLength;
2023
2407
 
2024
2408
  typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
2025
2409
  size_t* offsetPtr,
@@ -2101,15 +2485,19 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
2101
2485
  break; /* nothing found : store previous solution */
2102
2486
  }
2103
2487
 
2488
+ /* NOTE:
2489
+ * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
2490
+ * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
2491
+ * overflows the pointer, which is undefined behavior.
2492
+ */
2104
2493
  /* catch up */
2105
2494
  if (offset) {
2106
2495
  while ( (start > anchor)
2107
2496
  && (start > base+offset-ZSTD_REP_MOVE)
2108
- && (start[-1] == start[-1-offset+ZSTD_REP_MOVE]) ) /* only search for offset within prefix */
2497
+ && (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1]) ) /* only search for offset within prefix */
2109
2498
  { start--; matchLength++; }
2110
2499
  offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
2111
2500
  }
2112
-
2113
2501
  /* store sequence */
2114
2502
  _storeSequence:
2115
2503
  { size_t const litLength = start - anchor;
@@ -2182,8 +2570,8 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
2182
2570
  const BYTE* const dictEnd = dictBase + dictLimit;
2183
2571
  const BYTE* const dictStart = dictBase + ctx->lowLimit;
2184
2572
 
2185
- const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
2186
- const U32 mls = ctx->params.cParams.searchLength;
2573
+ const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
2574
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
2187
2575
 
2188
2576
  typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
2189
2577
  size_t* offsetPtr,
@@ -2370,7 +2758,7 @@ static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t src
2370
2758
  #endif
2371
2759
  }
2372
2760
 
2373
- static void ZSTD_compressBlock_btopt2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2761
+ static void ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2374
2762
  {
2375
2763
  #ifdef ZSTD_OPT_H_91842398743
2376
2764
  ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1);
@@ -2390,7 +2778,7 @@ static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, si
2390
2778
  #endif
2391
2779
  }
2392
2780
 
2393
- static void ZSTD_compressBlock_btopt2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2781
+ static void ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
2394
2782
  {
2395
2783
  #ifdef ZSTD_OPT_H_91842398743
2396
2784
  ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1);
@@ -2401,26 +2789,32 @@ static void ZSTD_compressBlock_btopt2_extDict(ZSTD_CCtx* ctx, const void* src, s
2401
2789
  }
2402
2790
 
2403
2791
 
2792
+ /* ZSTD_selectBlockCompressor() :
2793
+ * assumption : strat is a valid strategy */
2404
2794
  typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
2405
-
2406
2795
  static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
2407
2796
  {
2408
- static const ZSTD_blockCompressor blockCompressor[2][8] = {
2409
- { ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
2797
+ static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
2798
+ { ZSTD_compressBlock_fast /* default for 0 */,
2799
+ ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
2410
2800
  ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2,
2411
- ZSTD_compressBlock_btopt, ZSTD_compressBlock_btopt2 },
2412
- { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
2801
+ ZSTD_compressBlock_btopt, ZSTD_compressBlock_btultra },
2802
+ { ZSTD_compressBlock_fast_extDict /* default for 0 */,
2803
+ ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
2413
2804
  ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict,
2414
- ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btopt2_extDict }
2805
+ ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btultra_extDict }
2415
2806
  };
2807
+ ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
2808
+ assert((U32)strat >= (U32)ZSTD_fast);
2809
+ assert((U32)strat <= (U32)ZSTD_btultra);
2416
2810
 
2417
- return blockCompressor[extDict][(U32)strat];
2811
+ return blockCompressor[extDict!=0][(U32)strat];
2418
2812
  }
2419
2813
 
2420
2814
 
2421
2815
  static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2422
2816
  {
2423
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit);
2817
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, zc->lowLimit < zc->dictLimit);
2424
2818
  const BYTE* const base = zc->base;
2425
2819
  const BYTE* const istart = (const BYTE*)src;
2426
2820
  const U32 current = (U32)(istart-base);
@@ -2433,14 +2827,14 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCa
2433
2827
  }
2434
2828
 
2435
2829
 
2436
- /*! ZSTD_compress_generic() :
2830
+ /*! ZSTD_compress_frameChunk() :
2437
2831
  * Compress a chunk of data into one or multiple blocks.
2438
2832
  * All blocks will be terminated, all input will be consumed.
2439
2833
  * Function will issue an error if there is not enough `dstCapacity` to hold the compressed content.
2440
2834
  * Frame is supposed already started (header already produced)
2441
2835
  * @return : compressed size, or an error code
2442
2836
  */
2443
- static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2837
+ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2444
2838
  void* dst, size_t dstCapacity,
2445
2839
  const void* src, size_t srcSize,
2446
2840
  U32 lastFrameChunk)
@@ -2450,9 +2844,9 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2450
2844
  const BYTE* ip = (const BYTE*)src;
2451
2845
  BYTE* const ostart = (BYTE*)dst;
2452
2846
  BYTE* op = ostart;
2453
- U32 const maxDist = 1 << cctx->params.cParams.windowLog;
2847
+ U32 const maxDist = 1 << cctx->appliedParams.cParams.windowLog;
2454
2848
 
2455
- if (cctx->params.fParams.checksumFlag && srcSize)
2849
+ if (cctx->appliedParams.fParams.checksumFlag && srcSize)
2456
2850
  XXH64_update(&cctx->xxhState, src, srcSize);
2457
2851
 
2458
2852
  while (remaining) {
@@ -2465,9 +2859,9 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
2465
2859
 
2466
2860
  /* preemptive overflow correction */
2467
2861
  if (cctx->lowLimit > (3U<<29)) {
2468
- U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->params.cParams.hashLog, cctx->params.cParams.strategy)) - 1;
2862
+ U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->appliedParams.cParams.hashLog, cctx->appliedParams.cParams.strategy)) - 1;
2469
2863
  U32 const current = (U32)(ip - cctx->base);
2470
- U32 const newCurrent = (current & cycleMask) + (1 << cctx->params.cParams.windowLog);
2864
+ U32 const newCurrent = (current & cycleMask) + (1 << cctx->appliedParams.cParams.windowLog);
2471
2865
  U32 const correction = current - newCurrent;
2472
2866
  ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_64 <= 30);
2473
2867
  ZSTD_reduceIndex(cctx, correction);
@@ -2522,22 +2916,20 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2522
2916
  U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
2523
2917
  BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
2524
2918
  U32 const fcsCode = params.fParams.contentSizeFlag ?
2525
- (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : /* 0-3 */
2526
- 0;
2919
+ (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
2527
2920
  BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
2528
2921
  size_t pos;
2529
2922
 
2530
2923
  if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
2531
- DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u \n", !params.fParams.noDictIDFlag);
2532
- DEBUGLOG(5, "ZSTD_writeFrameHeader : dictID : %u \n", dictID);
2533
- DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDSizeCode : %u \n", dictIDSizeCode);
2924
+ DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
2925
+ !params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
2534
2926
 
2535
2927
  MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2536
2928
  op[4] = frameHeaderDecriptionByte; pos=5;
2537
2929
  if (!singleSegment) op[pos++] = windowLogByte;
2538
2930
  switch(dictIDSizeCode)
2539
2931
  {
2540
- default: /* impossible */
2932
+ default: assert(0); /* impossible */
2541
2933
  case 0 : break;
2542
2934
  case 1 : op[pos] = (BYTE)(dictID); pos++; break;
2543
2935
  case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;
@@ -2545,7 +2937,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2545
2937
  }
2546
2938
  switch(fcsCode)
2547
2939
  {
2548
- default: /* impossible */
2940
+ default: assert(0); /* impossible */
2549
2941
  case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;
2550
2942
  case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;
2551
2943
  case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;
@@ -2563,10 +2955,13 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2563
2955
  const BYTE* const ip = (const BYTE*) src;
2564
2956
  size_t fhSize = 0;
2565
2957
 
2958
+ DEBUGLOG(5, "ZSTD_compressContinue_internal");
2959
+ DEBUGLOG(5, "stage: %u", cctx->stage);
2566
2960
  if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
2567
2961
 
2568
2962
  if (frame && (cctx->stage==ZSTDcs_init)) {
2569
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, cctx->frameContentSize, cctx->dictID);
2963
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
2964
+ cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
2570
2965
  if (ZSTD_isError(fhSize)) return fhSize;
2571
2966
  dstCapacity -= fhSize;
2572
2967
  dst = (char*)dst + fhSize;
@@ -2596,7 +2991,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2596
2991
 
2597
2992
  if (srcSize) {
2598
2993
  size_t const cSize = frame ?
2599
- ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
2994
+ ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
2600
2995
  ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
2601
2996
  if (ZSTD_isError(cSize)) return cSize;
2602
2997
  cctx->consumedSrcSize += srcSize;
@@ -2614,14 +3009,18 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
2614
3009
  }
2615
3010
 
2616
3011
 
2617
- size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx)
3012
+ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
2618
3013
  {
2619
- return MIN (ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << cctx->params.cParams.windowLog);
3014
+ U32 const cLevel = cctx->compressionLevel;
3015
+ ZSTD_compressionParameters cParams = (cLevel == ZSTD_CLEVEL_CUSTOM) ?
3016
+ cctx->appliedParams.cParams :
3017
+ ZSTD_getCParams(cLevel, 0, 0);
3018
+ return MIN (ZSTD_BLOCKSIZE_MAX, 1 << cParams.windowLog);
2620
3019
  }
2621
3020
 
2622
3021
  size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
2623
3022
  {
2624
- size_t const blockSizeMax = ZSTD_getBlockSizeMax(cctx);
3023
+ size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
2625
3024
  if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
2626
3025
  return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
2627
3026
  }
@@ -2645,32 +3044,32 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
2645
3044
  zc->nextSrc = iend;
2646
3045
  if (srcSize <= HASH_READ_SIZE) return 0;
2647
3046
 
2648
- switch(zc->params.cParams.strategy)
3047
+ switch(zc->appliedParams.cParams.strategy)
2649
3048
  {
2650
3049
  case ZSTD_fast:
2651
- ZSTD_fillHashTable (zc, iend, zc->params.cParams.searchLength);
3050
+ ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
2652
3051
  break;
2653
3052
 
2654
3053
  case ZSTD_dfast:
2655
- ZSTD_fillDoubleHashTable (zc, iend, zc->params.cParams.searchLength);
3054
+ ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
2656
3055
  break;
2657
3056
 
2658
3057
  case ZSTD_greedy:
2659
3058
  case ZSTD_lazy:
2660
3059
  case ZSTD_lazy2:
2661
3060
  if (srcSize >= HASH_READ_SIZE)
2662
- ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength);
3061
+ ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->appliedParams.cParams.searchLength);
2663
3062
  break;
2664
3063
 
2665
3064
  case ZSTD_btlazy2:
2666
3065
  case ZSTD_btopt:
2667
- case ZSTD_btopt2:
3066
+ case ZSTD_btultra:
2668
3067
  if (srcSize >= HASH_READ_SIZE)
2669
- ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
3068
+ ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
2670
3069
  break;
2671
3070
 
2672
3071
  default:
2673
- return ERROR(GENERIC); /* strategy doesn't exist; impossible */
3072
+ assert(0); /* not possible : not a valid strategy id */
2674
3073
  }
2675
3074
 
2676
3075
  zc->nextToUpdate = (U32)(iend - zc->base);
@@ -2710,7 +3109,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
2710
3109
  BYTE scratchBuffer[1<<MAX(MLFSELog,LLFSELog)];
2711
3110
 
2712
3111
  dictPtr += 4; /* skip magic number */
2713
- cctx->dictID = cctx->params.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
3112
+ cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
2714
3113
  dictPtr += 4;
2715
3114
 
2716
3115
  { size_t const hufHeaderSize = HUF_readCTable(cctx->hufCTable, 255, dictPtr, dictEnd-dictPtr);
@@ -2781,28 +3180,56 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
2781
3180
 
2782
3181
  /** ZSTD_compress_insertDictionary() :
2783
3182
  * @return : 0, or an error code */
2784
- static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
3183
+ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
3184
+ const void* dict, size_t dictSize,
3185
+ ZSTD_dictMode_e dictMode)
2785
3186
  {
3187
+ DEBUGLOG(5, "ZSTD_compress_insertDictionary");
2786
3188
  if ((dict==NULL) || (dictSize<=8)) return 0;
2787
3189
 
2788
- /* dict as pure content */
2789
- if ((MEM_readLE32(dict) != ZSTD_DICT_MAGIC) || (cctx->forceRawDict))
3190
+ /* dict restricted modes */
3191
+ if (dictMode==ZSTD_dm_rawContent)
2790
3192
  return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
2791
3193
 
2792
- /* dict as zstd dictionary */
3194
+ if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
3195
+ if (dictMode == ZSTD_dm_auto) {
3196
+ DEBUGLOG(5, "raw content dictionary detected");
3197
+ return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
3198
+ }
3199
+ if (dictMode == ZSTD_dm_fullDict)
3200
+ return ERROR(dictionary_wrong);
3201
+ assert(0); /* impossible */
3202
+ }
3203
+
3204
+ /* dict as full zstd dictionary */
2793
3205
  return ZSTD_loadZstdDictionary(cctx, dict, dictSize);
2794
3206
  }
2795
3207
 
2796
3208
  /*! ZSTD_compressBegin_internal() :
2797
- * @return : 0, or an error code */
3209
+ * @return : 0, or an error code */
2798
3210
  static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2799
3211
  const void* dict, size_t dictSize,
2800
- ZSTD_parameters params, U64 pledgedSrcSize)
3212
+ ZSTD_dictMode_e dictMode,
3213
+ const ZSTD_CDict* cdict,
3214
+ ZSTD_parameters params, U64 pledgedSrcSize,
3215
+ ZSTD_buffered_policy_e zbuff)
2801
3216
  {
2802
- ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue;
3217
+ DEBUGLOG(4, "ZSTD_compressBegin_internal");
3218
+ DEBUGLOG(4, "dict ? %s", dict ? "dict" : (cdict ? "cdict" : "none"));
3219
+ DEBUGLOG(4, "dictMode : %u", (U32)dictMode);
3220
+ /* params are supposed to be fully validated at this point */
2803
3221
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
2804
- CHECK_F(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, crp));
2805
- return ZSTD_compress_insertDictionary(cctx, dict, dictSize);
3222
+ assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3223
+
3224
+ if (cdict && cdict->dictContentSize>0) {
3225
+ return ZSTD_copyCCtx_internal(cctx, cdict->refContext,
3226
+ params.fParams, pledgedSrcSize,
3227
+ zbuff);
3228
+ }
3229
+
3230
+ CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
3231
+ ZSTDcrp_continue, zbuff) );
3232
+ return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
2806
3233
  }
2807
3234
 
2808
3235
 
@@ -2814,14 +3241,16 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
2814
3241
  {
2815
3242
  /* compression parameters verification and optimization */
2816
3243
  CHECK_F(ZSTD_checkCParams(params.cParams));
2817
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, pledgedSrcSize);
3244
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
3245
+ params, pledgedSrcSize, ZSTDb_not_buffered);
2818
3246
  }
2819
3247
 
2820
3248
 
2821
3249
  size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
2822
3250
  {
2823
3251
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
2824
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0);
3252
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
3253
+ params, 0, ZSTDb_not_buffered);
2825
3254
  }
2826
3255
 
2827
3256
 
@@ -2840,11 +3269,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
2840
3269
  BYTE* op = ostart;
2841
3270
  size_t fhSize = 0;
2842
3271
 
3272
+ DEBUGLOG(5, "ZSTD_writeEpilogue");
2843
3273
  if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
2844
3274
 
2845
3275
  /* special case : empty frame */
2846
3276
  if (cctx->stage == ZSTDcs_init) {
2847
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, 0, 0);
3277
+ fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
2848
3278
  if (ZSTD_isError(fhSize)) return fhSize;
2849
3279
  dstCapacity -= fhSize;
2850
3280
  op += fhSize;
@@ -2860,7 +3290,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
2860
3290
  dstCapacity -= ZSTD_blockHeaderSize;
2861
3291
  }
2862
3292
 
2863
- if (cctx->params.fParams.checksumFlag) {
3293
+ if (cctx->appliedParams.fParams.checksumFlag) {
2864
3294
  U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
2865
3295
  if (dstCapacity<4) return ERROR(dstSize_tooSmall);
2866
3296
  MEM_writeLE32(op, checksum);
@@ -2877,13 +3307,19 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
2877
3307
  const void* src, size_t srcSize)
2878
3308
  {
2879
3309
  size_t endResult;
2880
- size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 1 /* last chunk */);
3310
+ size_t const cSize = ZSTD_compressContinue_internal(cctx,
3311
+ dst, dstCapacity, src, srcSize,
3312
+ 1 /* frame mode */, 1 /* last chunk */);
2881
3313
  if (ZSTD_isError(cSize)) return cSize;
2882
3314
  endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
2883
3315
  if (ZSTD_isError(endResult)) return endResult;
2884
- if (cctx->params.fParams.contentSizeFlag) { /* control src size */
2885
- if (cctx->frameContentSize != cctx->consumedSrcSize) return ERROR(srcSize_wrong);
2886
- }
3316
+ if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
3317
+ DEBUGLOG(5, "end of frame : controlling src size");
3318
+ if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
3319
+ DEBUGLOG(5, "error : pledgedSrcSize = %u, while realSrcSize = %u",
3320
+ (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
3321
+ return ERROR(srcSize_wrong);
3322
+ } }
2887
3323
  return cSize + endResult;
2888
3324
  }
2889
3325
 
@@ -2894,7 +3330,8 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
2894
3330
  const void* dict,size_t dictSize,
2895
3331
  ZSTD_parameters params)
2896
3332
  {
2897
- CHECK_F(ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize));
3333
+ CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
3334
+ params, srcSize, ZSTDb_not_buffered) );
2898
3335
  return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
2899
3336
  }
2900
3337
 
@@ -2926,25 +3363,36 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
2926
3363
  size_t result;
2927
3364
  ZSTD_CCtx ctxBody;
2928
3365
  memset(&ctxBody, 0, sizeof(ctxBody));
2929
- memcpy(&ctxBody.customMem, &defaultCustomMem, sizeof(ZSTD_customMem));
3366
+ ctxBody.customMem = ZSTD_defaultCMem;
2930
3367
  result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
2931
- ZSTD_free(ctxBody.workSpace, defaultCustomMem); /* can't free ctxBody itself, as it's on stack; free only heap content */
3368
+ ZSTD_free(ctxBody.workSpace, ZSTD_defaultCMem); /* can't free ctxBody itself, as it's on stack; free only heap content */
2932
3369
  return result;
2933
3370
  }
2934
3371
 
2935
3372
 
2936
3373
  /* ===== Dictionary API ===== */
2937
3374
 
2938
- struct ZSTD_CDict_s {
2939
- void* dictBuffer;
2940
- const void* dictContent;
2941
- size_t dictContentSize;
2942
- ZSTD_CCtx* refContext;
2943
- }; /* typedef'd tp ZSTD_CDict within "zstd.h" */
3375
+ /*! ZSTD_estimateCDictSize_advanced() :
3376
+ * Estimate amount of memory that will be needed to create a dictionary with following arguments */
3377
+ size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, unsigned byReference)
3378
+ {
3379
+ DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
3380
+ DEBUGLOG(5, "CCtx estimate : %u", (U32)ZSTD_estimateCCtxSize_advanced(cParams));
3381
+ return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_advanced(cParams)
3382
+ + (byReference ? 0 : dictSize);
3383
+ }
3384
+
3385
+ size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
3386
+ {
3387
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3388
+ return ZSTD_estimateCDictSize_advanced(dictSize, cParams, 0);
3389
+ }
2944
3390
 
2945
3391
  size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
2946
3392
  {
2947
3393
  if (cdict==NULL) return 0; /* support sizeof on NULL */
3394
+ DEBUGLOG(5, "sizeof(*cdict) : %u", (U32)sizeof(*cdict));
3395
+ DEBUGLOG(5, "ZSTD_sizeof_CCtx : %u", (U32)ZSTD_sizeof_CCtx(cdict->refContext));
2948
3396
  return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
2949
3397
  }
2950
3398
 
@@ -2956,13 +3404,46 @@ static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_
2956
3404
  return params;
2957
3405
  }
2958
3406
 
2959
- ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
3407
+ static size_t ZSTD_initCDict_internal(
3408
+ ZSTD_CDict* cdict,
3409
+ const void* dictBuffer, size_t dictSize,
3410
+ unsigned byReference, ZSTD_dictMode_e dictMode,
3411
+ ZSTD_compressionParameters cParams)
3412
+ {
3413
+ DEBUGLOG(5, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
3414
+ if ((byReference) || (!dictBuffer) || (!dictSize)) {
3415
+ cdict->dictBuffer = NULL;
3416
+ cdict->dictContent = dictBuffer;
3417
+ } else {
3418
+ void* const internalBuffer = ZSTD_malloc(dictSize, cdict->refContext->customMem);
3419
+ cdict->dictBuffer = internalBuffer;
3420
+ cdict->dictContent = internalBuffer;
3421
+ if (!internalBuffer) return ERROR(memory_allocation);
3422
+ memcpy(internalBuffer, dictBuffer, dictSize);
3423
+ }
3424
+ cdict->dictContentSize = dictSize;
3425
+
3426
+ { ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */,
3427
+ 0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
3428
+ ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
3429
+ CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
3430
+ cdict->dictContent, dictSize, dictMode,
3431
+ NULL,
3432
+ params, ZSTD_CONTENTSIZE_UNKNOWN,
3433
+ ZSTDb_not_buffered) );
3434
+ }
3435
+
3436
+ return 0;
3437
+ }
3438
+
3439
+ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
3440
+ unsigned byReference, ZSTD_dictMode_e dictMode,
2960
3441
  ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
2961
3442
  {
2962
- if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
2963
- if (!customMem.customAlloc || !customMem.customFree) return NULL;
3443
+ DEBUGLOG(5, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
3444
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
2964
3445
 
2965
- { ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
3446
+ { ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
2966
3447
  ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
2967
3448
 
2968
3449
  if (!cdict || !cctx) {
@@ -2970,46 +3451,34 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, u
2970
3451
  ZSTD_freeCCtx(cctx);
2971
3452
  return NULL;
2972
3453
  }
3454
+ cdict->refContext = cctx;
2973
3455
 
2974
- if ((byReference) || (!dictBuffer) || (!dictSize)) {
2975
- cdict->dictBuffer = NULL;
2976
- cdict->dictContent = dictBuffer;
2977
- } else {
2978
- void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
2979
- if (!internalBuffer) { ZSTD_free(cctx, customMem); ZSTD_free(cdict, customMem); return NULL; }
2980
- memcpy(internalBuffer, dictBuffer, dictSize);
2981
- cdict->dictBuffer = internalBuffer;
2982
- cdict->dictContent = internalBuffer;
3456
+ if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3457
+ dictBuffer, dictSize,
3458
+ byReference, dictMode,
3459
+ cParams) )) {
3460
+ ZSTD_freeCDict(cdict);
3461
+ return NULL;
2983
3462
  }
2984
3463
 
2985
- { ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
2986
- ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
2987
- size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
2988
- if (ZSTD_isError(errorCode)) {
2989
- ZSTD_free(cdict->dictBuffer, customMem);
2990
- ZSTD_free(cdict, customMem);
2991
- ZSTD_freeCCtx(cctx);
2992
- return NULL;
2993
- } }
2994
-
2995
- cdict->refContext = cctx;
2996
- cdict->dictContentSize = dictSize;
2997
3464
  return cdict;
2998
3465
  }
2999
3466
  }
3000
3467
 
3001
3468
  ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
3002
3469
  {
3003
- ZSTD_customMem const allocator = { NULL, NULL, NULL };
3004
3470
  ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3005
- return ZSTD_createCDict_advanced(dict, dictSize, 0, cParams, allocator);
3471
+ return ZSTD_createCDict_advanced(dict, dictSize,
3472
+ 0 /* byReference */, ZSTD_dm_auto,
3473
+ cParams, ZSTD_defaultCMem);
3006
3474
  }
3007
3475
 
3008
3476
  ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
3009
3477
  {
3010
- ZSTD_customMem const allocator = { NULL, NULL, NULL };
3011
3478
  ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
3012
- return ZSTD_createCDict_advanced(dict, dictSize, 1, cParams, allocator);
3479
+ return ZSTD_createCDict_advanced(dict, dictSize,
3480
+ 1 /* byReference */, ZSTD_dm_auto,
3481
+ cParams, ZSTD_defaultCMem);
3013
3482
  }
3014
3483
 
3015
3484
  size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
@@ -3023,7 +3492,54 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
3023
3492
  }
3024
3493
  }
3025
3494
 
3026
- static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
3495
+ /*! ZSTD_initStaticCDict_advanced() :
3496
+ * Generate a digested dictionary in provided memory area.
3497
+ * workspace: The memory area to emplace the dictionary into.
3498
+ * Provided pointer must 8-bytes aligned.
3499
+ * It must outlive dictionary usage.
3500
+ * workspaceSize: Use ZSTD_estimateCDictSize()
3501
+ * to determine how large workspace must be.
3502
+ * cParams : use ZSTD_getCParams() to transform a compression level
3503
+ * into its relevants cParams.
3504
+ * @return : pointer to ZSTD_CDict*, or NULL if error (size too small)
3505
+ * Note : there is no corresponding "free" function.
3506
+ * Since workspace was allocated externally, it must be freed externally.
3507
+ */
3508
+ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
3509
+ const void* dict, size_t dictSize,
3510
+ unsigned byReference, ZSTD_dictMode_e dictMode,
3511
+ ZSTD_compressionParameters cParams)
3512
+ {
3513
+ size_t const cctxSize = ZSTD_estimateCCtxSize_advanced(cParams);
3514
+ size_t const neededSize = sizeof(ZSTD_CDict) + (byReference ? 0 : dictSize)
3515
+ + cctxSize;
3516
+ ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
3517
+ void* ptr;
3518
+ DEBUGLOG(5, "(size_t)workspace & 7 : %u", (U32)(size_t)workspace & 7);
3519
+ if ((size_t)workspace & 7) return NULL; /* 8-aligned */
3520
+ DEBUGLOG(5, "(workspaceSize < neededSize) : (%u < %u) => %u",
3521
+ (U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
3522
+ if (workspaceSize < neededSize) return NULL;
3523
+
3524
+ if (!byReference) {
3525
+ memcpy(cdict+1, dict, dictSize);
3526
+ dict = cdict+1;
3527
+ ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
3528
+ } else {
3529
+ ptr = cdict+1;
3530
+ }
3531
+ cdict->refContext = ZSTD_initStaticCCtx(ptr, cctxSize);
3532
+
3533
+ if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
3534
+ dict, dictSize,
3535
+ 1 /* byReference */, dictMode,
3536
+ cParams) ))
3537
+ return NULL;
3538
+
3539
+ return cdict;
3540
+ }
3541
+
3542
+ ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
3027
3543
  return ZSTD_getParamsFromCCtx(cdict->refContext);
3028
3544
  }
3029
3545
 
@@ -3033,16 +3549,16 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3033
3549
  ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
3034
3550
  ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
3035
3551
  {
3036
- if (cdict==NULL) return ERROR(GENERIC); /* does not support NULL cdict */
3037
- DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced : dictIDFlag == %u \n", !fParams.noDictIDFlag);
3038
- if (cdict->dictContentSize)
3039
- CHECK_F( ZSTD_copyCCtx_internal(cctx, cdict->refContext, fParams, pledgedSrcSize) )
3040
- else {
3041
- ZSTD_parameters params = cdict->refContext->params;
3552
+ if (cdict==NULL) return ERROR(dictionary_wrong);
3553
+ { ZSTD_parameters params = cdict->refContext->appliedParams;
3042
3554
  params.fParams = fParams;
3043
- CHECK_F(ZSTD_compressBegin_internal(cctx, NULL, 0, params, pledgedSrcSize));
3555
+ DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced");
3556
+ return ZSTD_compressBegin_internal(cctx,
3557
+ NULL, 0, ZSTD_dm_auto,
3558
+ cdict,
3559
+ params, pledgedSrcSize,
3560
+ ZSTDb_not_buffered);
3044
3561
  }
3045
- return 0;
3046
3562
  }
3047
3563
 
3048
3564
  /* ZSTD_compressBegin_usingCDict() :
@@ -3051,7 +3567,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
3051
3567
  size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
3052
3568
  {
3053
3569
  ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
3054
- DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u \n", !fParams.noDictIDFlag);
3570
+ DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
3055
3571
  return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
3056
3572
  }
3057
3573
 
@@ -3084,176 +3600,133 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
3084
3600
  * Streaming
3085
3601
  ********************************************************************/
3086
3602
 
3087
- typedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage;
3088
-
3089
- struct ZSTD_CStream_s {
3090
- ZSTD_CCtx* cctx;
3091
- ZSTD_CDict* cdictLocal;
3092
- const ZSTD_CDict* cdict;
3093
- char* inBuff;
3094
- size_t inBuffSize;
3095
- size_t inToCompress;
3096
- size_t inBuffPos;
3097
- size_t inBuffTarget;
3098
- size_t blockSize;
3099
- char* outBuff;
3100
- size_t outBuffSize;
3101
- size_t outBuffContentSize;
3102
- size_t outBuffFlushedSize;
3103
- ZSTD_cStreamStage stage;
3104
- U32 checksum;
3105
- U32 frameEnded;
3106
- U64 pledgedSrcSize;
3107
- ZSTD_parameters params;
3108
- ZSTD_customMem customMem;
3109
- }; /* typedef'd to ZSTD_CStream within "zstd.h" */
3110
-
3111
3603
  ZSTD_CStream* ZSTD_createCStream(void)
3112
3604
  {
3113
- return ZSTD_createCStream_advanced(defaultCustomMem);
3605
+ return ZSTD_createCStream_advanced(ZSTD_defaultCMem);
3114
3606
  }
3115
3607
 
3116
- ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
3608
+ ZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize)
3117
3609
  {
3118
- ZSTD_CStream* zcs;
3119
-
3120
- if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
3121
- if (!customMem.customAlloc || !customMem.customFree) return NULL;
3610
+ return ZSTD_initStaticCCtx(workspace, workspaceSize);
3611
+ }
3122
3612
 
3123
- zcs = (ZSTD_CStream*)ZSTD_malloc(sizeof(ZSTD_CStream), customMem);
3124
- if (zcs==NULL) return NULL;
3125
- memset(zcs, 0, sizeof(ZSTD_CStream));
3126
- memcpy(&zcs->customMem, &customMem, sizeof(ZSTD_customMem));
3127
- zcs->cctx = ZSTD_createCCtx_advanced(customMem);
3128
- if (zcs->cctx == NULL) { ZSTD_freeCStream(zcs); return NULL; }
3129
- return zcs;
3613
+ ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
3614
+ { /* CStream and CCtx are now same object */
3615
+ return ZSTD_createCCtx_advanced(customMem);
3130
3616
  }
3131
3617
 
3132
3618
  size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
3133
3619
  {
3134
- if (zcs==NULL) return 0; /* support free on NULL */
3135
- { ZSTD_customMem const cMem = zcs->customMem;
3136
- ZSTD_freeCCtx(zcs->cctx);
3137
- zcs->cctx = NULL;
3138
- ZSTD_freeCDict(zcs->cdictLocal);
3139
- zcs->cdictLocal = NULL;
3140
- ZSTD_free(zcs->inBuff, cMem);
3141
- zcs->inBuff = NULL;
3142
- ZSTD_free(zcs->outBuff, cMem);
3143
- zcs->outBuff = NULL;
3144
- ZSTD_free(zcs, cMem);
3145
- return 0;
3146
- }
3620
+ return ZSTD_freeCCtx(zcs); /* same object */
3147
3621
  }
3148
3622
 
3149
3623
 
3624
+
3150
3625
  /*====== Initialization ======*/
3151
3626
 
3152
- size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
3627
+ size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX; }
3153
3628
 
3154
3629
  size_t ZSTD_CStreamOutSize(void)
3155
3630
  {
3156
- return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
3631
+ return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
3157
3632
  }
3158
3633
 
3159
- static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3634
+ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
3635
+ const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
3636
+ const ZSTD_CDict* cdict,
3637
+ ZSTD_parameters params, unsigned long long pledgedSrcSize)
3160
3638
  {
3161
- if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */
3162
-
3163
- DEBUGLOG(5, "ZSTD_resetCStream_internal : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
3639
+ DEBUGLOG(4, "ZSTD_resetCStream_internal");
3640
+ /* params are supposed to be fully validated at this point */
3641
+ assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3642
+ assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3164
3643
 
3165
- if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict_advanced(zcs->cctx, zcs->cdict, zcs->params.fParams, pledgedSrcSize))
3166
- else CHECK_F(ZSTD_compressBegin_internal(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize));
3644
+ CHECK_F( ZSTD_compressBegin_internal(zcs,
3645
+ dict, dictSize, dictMode,
3646
+ cdict,
3647
+ params, pledgedSrcSize,
3648
+ ZSTDb_buffered) );
3167
3649
 
3168
3650
  zcs->inToCompress = 0;
3169
3651
  zcs->inBuffPos = 0;
3170
3652
  zcs->inBuffTarget = zcs->blockSize;
3171
3653
  zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
3172
- zcs->stage = zcss_load;
3654
+ zcs->streamStage = zcss_load;
3173
3655
  zcs->frameEnded = 0;
3174
- zcs->pledgedSrcSize = pledgedSrcSize;
3175
3656
  return 0; /* ready to go */
3176
3657
  }
3177
3658
 
3178
3659
  size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3179
3660
  {
3180
-
3181
- zcs->params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
3182
- DEBUGLOG(5, "ZSTD_resetCStream : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
3183
- return ZSTD_resetCStream_internal(zcs, pledgedSrcSize);
3661
+ ZSTD_parameters params = zcs->requestedParams;
3662
+ params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
3663
+ DEBUGLOG(5, "ZSTD_resetCStream");
3664
+ if (zcs->compressionLevel != ZSTD_CLEVEL_CUSTOM) {
3665
+ params.cParams = ZSTD_getCParams(zcs->compressionLevel, pledgedSrcSize, 0 /* dictSize */);
3666
+ }
3667
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
3184
3668
  }
3185
3669
 
3186
- /* ZSTD_initCStream_internal() :
3187
- * params are supposed validated at this stage
3188
- * and zcs->cdict is supposed to be correct */
3189
- static size_t ZSTD_initCStream_stage2(ZSTD_CStream* zcs,
3190
- const ZSTD_parameters params,
3191
- unsigned long long pledgedSrcSize)
3670
+ /*! ZSTD_initCStream_internal() :
3671
+ * Note : not static, but hidden (not exposed). Used by zstdmt_compress.c
3672
+ * Assumption 1 : params are valid
3673
+ * Assumption 2 : either dict, or cdict, is defined, not both */
3674
+ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3675
+ const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3676
+ ZSTD_parameters params, unsigned long long pledgedSrcSize)
3192
3677
  {
3678
+ DEBUGLOG(5, "ZSTD_initCStream_internal");
3193
3679
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3680
+ assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3194
3681
 
3195
- /* allocate buffers */
3196
- { size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog;
3197
- if (zcs->inBuffSize < neededInBuffSize) {
3198
- zcs->inBuffSize = 0;
3199
- ZSTD_free(zcs->inBuff, zcs->customMem);
3200
- zcs->inBuff = (char*) ZSTD_malloc(neededInBuffSize, zcs->customMem);
3201
- if (zcs->inBuff == NULL) return ERROR(memory_allocation);
3202
- zcs->inBuffSize = neededInBuffSize;
3682
+ if (dict && dictSize >= 8) {
3683
+ DEBUGLOG(5, "loading dictionary of size %u", (U32)dictSize);
3684
+ if (zcs->staticSize) { /* static CCtx : never uses malloc */
3685
+ /* incompatible with internal cdict creation */
3686
+ return ERROR(memory_allocation);
3203
3687
  }
3204
- zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize);
3205
- }
3206
- if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) {
3207
- size_t const outBuffSize = ZSTD_compressBound(zcs->blockSize)+1;
3208
- zcs->outBuffSize = 0;
3209
- ZSTD_free(zcs->outBuff, zcs->customMem);
3210
- zcs->outBuff = (char*) ZSTD_malloc(outBuffSize, zcs->customMem);
3211
- if (zcs->outBuff == NULL) return ERROR(memory_allocation);
3212
- zcs->outBuffSize = outBuffSize;
3688
+ ZSTD_freeCDict(zcs->cdictLocal);
3689
+ zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
3690
+ zcs->dictContentByRef, zcs->dictMode,
3691
+ params.cParams, zcs->customMem);
3692
+ zcs->cdict = zcs->cdictLocal;
3693
+ if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
3694
+ } else {
3695
+ if (cdict) {
3696
+ ZSTD_parameters const cdictParams = ZSTD_getParamsFromCDict(cdict);
3697
+ params.cParams = cdictParams.cParams; /* cParams are enforced from cdict */
3698
+ }
3699
+ ZSTD_freeCDict(zcs->cdictLocal);
3700
+ zcs->cdictLocal = NULL;
3701
+ zcs->cdict = cdict;
3213
3702
  }
3214
3703
 
3215
- zcs->checksum = params.fParams.checksumFlag > 0;
3216
- zcs->params = params;
3217
-
3218
- DEBUGLOG(5, "ZSTD_initCStream_stage2 : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
3219
- return ZSTD_resetCStream_internal(zcs, pledgedSrcSize);
3704
+ zcs->requestedParams = params;
3705
+ zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
3706
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
3220
3707
  }
3221
3708
 
3222
3709
  /* ZSTD_initCStream_usingCDict_advanced() :
3223
3710
  * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
3224
- size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams)
3225
- {
3226
- if (!cdict) return ERROR(GENERIC); /* cannot handle NULL cdict (does not know what to do) */
3711
+ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
3712
+ const ZSTD_CDict* cdict,
3713
+ ZSTD_frameParameters fParams,
3714
+ unsigned long long pledgedSrcSize)
3715
+ { /* cannot handle NULL cdict (does not know what to do) */
3716
+ if (!cdict) return ERROR(dictionary_wrong);
3227
3717
  { ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
3228
3718
  params.fParams = fParams;
3229
- zcs->cdict = cdict;
3230
- return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
3719
+ return ZSTD_initCStream_internal(zcs,
3720
+ NULL, 0, cdict,
3721
+ params, pledgedSrcSize);
3231
3722
  }
3232
3723
  }
3233
3724
 
3234
3725
  /* note : cdict must outlive compression session */
3235
3726
  size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
3236
3727
  {
3237
- ZSTD_frameParameters const fParams = { 0 /* content */, 0 /* checksum */, 0 /* noDictID */ };
3238
- return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, 0, fParams);
3239
- }
3240
-
3241
- static size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3242
- const void* dict, size_t dictSize,
3243
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
3244
- {
3245
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3246
- zcs->cdict = NULL;
3247
-
3248
- if (dict && dictSize >= 8) {
3249
- ZSTD_freeCDict(zcs->cdictLocal);
3250
- zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0 /* copy */, params.cParams, zcs->customMem);
3251
- if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
3252
- zcs->cdict = zcs->cdictLocal;
3253
- }
3254
-
3255
- DEBUGLOG(5, "ZSTD_initCStream_internal : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
3256
- return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
3728
+ ZSTD_frameParameters const fParams = { 0 /* contentSize */, 0 /* checksum */, 0 /* hideDictID */ };
3729
+ return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, 0); /* note : will check that cdict != NULL */
3257
3730
  }
3258
3731
 
3259
3732
  size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
@@ -3261,120 +3734,180 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3261
3734
  ZSTD_parameters params, unsigned long long pledgedSrcSize)
3262
3735
  {
3263
3736
  CHECK_F( ZSTD_checkCParams(params.cParams) );
3264
- DEBUGLOG(5, "ZSTD_initCStream_advanced : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
3265
- return ZSTD_initCStream_internal(zcs, dict, dictSize, params, pledgedSrcSize);
3737
+ zcs->requestedParams = params;
3738
+ zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
3739
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, pledgedSrcSize);
3266
3740
  }
3267
3741
 
3268
3742
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3269
3743
  {
3270
3744
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
3271
- return ZSTD_initCStream_internal(zcs, dict, dictSize, params, 0);
3745
+ zcs->compressionLevel = compressionLevel;
3746
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, 0);
3272
3747
  }
3273
3748
 
3274
3749
  size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
3275
3750
  {
3276
3751
  ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
3277
3752
  params.fParams.contentSizeFlag = (pledgedSrcSize>0);
3278
- return ZSTD_initCStream_internal(zcs, NULL, 0, params, pledgedSrcSize);
3753
+ return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, pledgedSrcSize);
3279
3754
  }
3280
3755
 
3281
3756
  size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
3282
3757
  {
3283
3758
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
3284
- return ZSTD_initCStream_internal(zcs, NULL, 0, params, 0);
3285
- }
3286
-
3287
- size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
3288
- {
3289
- if (zcs==NULL) return 0; /* support sizeof on NULL */
3290
- return sizeof(*zcs) + ZSTD_sizeof_CCtx(zcs->cctx) + ZSTD_sizeof_CDict(zcs->cdictLocal) + zcs->outBuffSize + zcs->inBuffSize;
3759
+ return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
3291
3760
  }
3292
3761
 
3293
3762
  /*====== Compression ======*/
3294
3763
 
3295
- typedef enum { zsf_gather, zsf_flush, zsf_end } ZSTD_flush_e;
3296
-
3297
- MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
3764
+ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
3765
+ const void* src, size_t srcSize)
3298
3766
  {
3299
3767
  size_t const length = MIN(dstCapacity, srcSize);
3300
- memcpy(dst, src, length);
3768
+ if (length) memcpy(dst, src, length);
3301
3769
  return length;
3302
3770
  }
3303
3771
 
3304
- static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3305
- void* dst, size_t* dstCapacityPtr,
3306
- const void* src, size_t* srcSizePtr,
3307
- ZSTD_flush_e const flush)
3772
+ /** ZSTD_compressStream_generic():
3773
+ * internal function for all *compressStream*() variants and *compress_generic()
3774
+ * @return : hint size for next input */
3775
+ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3776
+ ZSTD_outBuffer* output,
3777
+ ZSTD_inBuffer* input,
3778
+ ZSTD_EndDirective const flushMode)
3308
3779
  {
3780
+ const char* const istart = (const char*)input->src;
3781
+ const char* const iend = istart + input->size;
3782
+ const char* ip = istart + input->pos;
3783
+ char* const ostart = (char*)output->dst;
3784
+ char* const oend = ostart + output->size;
3785
+ char* op = ostart + output->pos;
3309
3786
  U32 someMoreWork = 1;
3310
- const char* const istart = (const char*)src;
3311
- const char* const iend = istart + *srcSizePtr;
3312
- const char* ip = istart;
3313
- char* const ostart = (char*)dst;
3314
- char* const oend = ostart + *dstCapacityPtr;
3315
- char* op = ostart;
3787
+
3788
+ /* check expectations */
3789
+ DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (U32)flushMode);
3790
+ assert(zcs->inBuff != NULL);
3791
+ assert(zcs->inBuffSize>0);
3792
+ assert(zcs->outBuff!= NULL);
3793
+ assert(zcs->outBuffSize>0);
3794
+ assert(output->pos <= output->size);
3795
+ assert(input->pos <= input->size);
3316
3796
 
3317
3797
  while (someMoreWork) {
3318
- switch(zcs->stage)
3798
+ switch(zcs->streamStage)
3319
3799
  {
3320
- case zcss_init: return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */
3800
+ case zcss_init:
3801
+ /* call ZSTD_initCStream() first ! */
3802
+ return ERROR(init_missing);
3321
3803
 
3322
3804
  case zcss_load:
3323
- /* complete inBuffer */
3805
+ if ( (flushMode == ZSTD_e_end)
3806
+ && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */
3807
+ && (zcs->inBuffPos == 0) ) {
3808
+ /* shortcut to compression pass directly into output buffer */
3809
+ size_t const cSize = ZSTD_compressEnd(zcs,
3810
+ op, oend-op, ip, iend-ip);
3811
+ DEBUGLOG(4, "ZSTD_compressEnd : %u", (U32)cSize);
3812
+ if (ZSTD_isError(cSize)) return cSize;
3813
+ ip = iend;
3814
+ op += cSize;
3815
+ zcs->frameEnded = 1;
3816
+ ZSTD_startNewCompression(zcs);
3817
+ someMoreWork = 0; break;
3818
+ }
3819
+ /* complete loading into inBuffer */
3324
3820
  { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
3325
- size_t const loaded = ZSTD_limitCopy(zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip);
3821
+ size_t const loaded = ZSTD_limitCopy(
3822
+ zcs->inBuff + zcs->inBuffPos, toLoad,
3823
+ ip, iend-ip);
3326
3824
  zcs->inBuffPos += loaded;
3327
3825
  ip += loaded;
3328
- if ( (zcs->inBuffPos==zcs->inToCompress) || (!flush && (toLoad != loaded)) ) {
3329
- someMoreWork = 0; break; /* not enough input to get a full block : stop there, wait for more */
3330
- } }
3826
+ if ( (flushMode == ZSTD_e_continue)
3827
+ && (zcs->inBuffPos < zcs->inBuffTarget) ) {
3828
+ /* not enough input to fill full block : stop here */
3829
+ someMoreWork = 0; break;
3830
+ }
3831
+ if ( (flushMode == ZSTD_e_flush)
3832
+ && (zcs->inBuffPos == zcs->inToCompress) ) {
3833
+ /* empty */
3834
+ someMoreWork = 0; break;
3835
+ }
3836
+ }
3331
3837
  /* compress current block (note : this stage cannot be stopped in the middle) */
3838
+ DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode);
3332
3839
  { void* cDst;
3333
3840
  size_t cSize;
3334
3841
  size_t const iSize = zcs->inBuffPos - zcs->inToCompress;
3335
3842
  size_t oSize = oend-op;
3843
+ unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
3336
3844
  if (oSize >= ZSTD_compressBound(iSize))
3337
- cDst = op; /* compress directly into output buffer (avoid flush stage) */
3845
+ cDst = op; /* compress into output buffer, to skip flush stage */
3338
3846
  else
3339
3847
  cDst = zcs->outBuff, oSize = zcs->outBuffSize;
3340
- cSize = (flush == zsf_end) ?
3341
- ZSTD_compressEnd(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) :
3342
- ZSTD_compressContinue(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize);
3848
+ cSize = lastBlock ?
3849
+ ZSTD_compressEnd(zcs, cDst, oSize,
3850
+ zcs->inBuff + zcs->inToCompress, iSize) :
3851
+ ZSTD_compressContinue(zcs, cDst, oSize,
3852
+ zcs->inBuff + zcs->inToCompress, iSize);
3343
3853
  if (ZSTD_isError(cSize)) return cSize;
3344
- if (flush == zsf_end) zcs->frameEnded = 1;
3854
+ zcs->frameEnded = lastBlock;
3345
3855
  /* prepare next block */
3346
3856
  zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
3347
3857
  if (zcs->inBuffTarget > zcs->inBuffSize)
3348
- zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffSize >= blockSize */
3858
+ zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
3859
+ DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
3860
+ (U32)zcs->inBuffTarget, (U32)zcs->inBuffSize);
3861
+ if (!lastBlock)
3862
+ assert(zcs->inBuffTarget <= zcs->inBuffSize);
3349
3863
  zcs->inToCompress = zcs->inBuffPos;
3350
- if (cDst == op) { op += cSize; break; } /* no need to flush */
3864
+ if (cDst == op) { /* no need to flush */
3865
+ op += cSize;
3866
+ if (zcs->frameEnded) {
3867
+ DEBUGLOG(5, "Frame completed directly in outBuffer");
3868
+ someMoreWork = 0;
3869
+ ZSTD_startNewCompression(zcs);
3870
+ }
3871
+ break;
3872
+ }
3351
3873
  zcs->outBuffContentSize = cSize;
3352
3874
  zcs->outBuffFlushedSize = 0;
3353
- zcs->stage = zcss_flush; /* pass-through to flush stage */
3875
+ zcs->streamStage = zcss_flush; /* pass-through to flush stage */
3354
3876
  }
3355
-
3877
+ /* fall-through */
3356
3878
  case zcss_flush:
3879
+ DEBUGLOG(5, "flush stage");
3357
3880
  { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
3358
- size_t const flushed = ZSTD_limitCopy(op, oend-op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
3881
+ size_t const flushed = ZSTD_limitCopy(op, oend-op,
3882
+ zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
3883
+ DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
3884
+ (U32)toFlush, (U32)(oend-op), (U32)flushed);
3359
3885
  op += flushed;
3360
3886
  zcs->outBuffFlushedSize += flushed;
3361
- if (toFlush!=flushed) { someMoreWork = 0; break; } /* dst too small to store flushed data : stop there */
3887
+ if (toFlush!=flushed) {
3888
+ /* flush not fully completed, presumably because dst is too small */
3889
+ assert(op==oend);
3890
+ someMoreWork = 0;
3891
+ break;
3892
+ }
3362
3893
  zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
3363
- zcs->stage = zcss_load;
3894
+ if (zcs->frameEnded) {
3895
+ DEBUGLOG(5, "Frame completed on flush");
3896
+ someMoreWork = 0;
3897
+ ZSTD_startNewCompression(zcs);
3898
+ break;
3899
+ }
3900
+ zcs->streamStage = zcss_load;
3364
3901
  break;
3365
3902
  }
3366
3903
 
3367
- case zcss_final:
3368
- someMoreWork = 0; /* do nothing */
3369
- break;
3370
-
3371
- default:
3372
- return ERROR(GENERIC); /* impossible */
3904
+ default: /* impossible */
3905
+ assert(0);
3373
3906
  }
3374
3907
  }
3375
3908
 
3376
- *srcSizePtr = ip - istart;
3377
- *dstCapacityPtr = op - ostart;
3909
+ input->pos = ip - istart;
3910
+ output->pos = op - ostart;
3378
3911
  if (zcs->frameEnded) return 0;
3379
3912
  { size_t hintInSize = zcs->inBuffTarget - zcs->inBuffPos;
3380
3913
  if (hintInSize==0) hintInSize = zcs->blockSize;
@@ -3384,14 +3917,86 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
3384
3917
 
3385
3918
  size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
3386
3919
  {
3387
- size_t sizeRead = input->size - input->pos;
3388
- size_t sizeWritten = output->size - output->pos;
3389
- size_t const result = ZSTD_compressStream_generic(zcs,
3390
- (char*)(output->dst) + output->pos, &sizeWritten,
3391
- (const char*)(input->src) + input->pos, &sizeRead, zsf_gather);
3392
- input->pos += sizeRead;
3393
- output->pos += sizeWritten;
3394
- return result;
3920
+ /* check conditions */
3921
+ if (output->pos > output->size) return ERROR(GENERIC);
3922
+ if (input->pos > input->size) return ERROR(GENERIC);
3923
+
3924
+ return ZSTD_compressStream_generic(zcs, output, input, ZSTD_e_continue);
3925
+ }
3926
+
3927
+ /*! ZSTDMT_initCStream_internal() :
3928
+ * Private use only. Init streaming operation.
3929
+ * expects params to be valid.
3930
+ * must receive dict, or cdict, or none, but not both.
3931
+ * @return : 0, or an error code */
3932
+ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
3933
+ const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
3934
+ ZSTD_parameters params, unsigned long long pledgedSrcSize);
3935
+
3936
+
3937
+ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3938
+ ZSTD_outBuffer* output,
3939
+ ZSTD_inBuffer* input,
3940
+ ZSTD_EndDirective endOp)
3941
+ {
3942
+ /* check conditions */
3943
+ if (output->pos > output->size) return ERROR(GENERIC);
3944
+ if (input->pos > input->size) return ERROR(GENERIC);
3945
+ assert(cctx!=NULL);
3946
+
3947
+ /* transparent initialization stage */
3948
+ if (cctx->streamStage == zcss_init) {
3949
+ const void* const prefix = cctx->prefix;
3950
+ size_t const prefixSize = cctx->prefixSize;
3951
+ ZSTD_parameters params = cctx->requestedParams;
3952
+ if (cctx->compressionLevel != ZSTD_CLEVEL_CUSTOM)
3953
+ params.cParams = ZSTD_getCParams(cctx->compressionLevel,
3954
+ cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
3955
+ cctx->prefix = NULL; cctx->prefixSize = 0; /* single usage */
3956
+ assert(prefix==NULL || cctx->cdict==NULL); /* only one can be set */
3957
+
3958
+ #ifdef ZSTD_MULTITHREAD
3959
+ if (cctx->nbThreads > 1) {
3960
+ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", cctx->nbThreads);
3961
+ CHECK_F( ZSTDMT_initCStream_internal(cctx->mtctx, prefix, prefixSize, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
3962
+ cctx->streamStage = zcss_load;
3963
+ } else
3964
+ #endif
3965
+ {
3966
+ CHECK_F( ZSTD_resetCStream_internal(cctx, prefix, prefixSize, cctx->dictMode, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
3967
+ } }
3968
+
3969
+ /* compression stage */
3970
+ #ifdef ZSTD_MULTITHREAD
3971
+ if (cctx->nbThreads > 1) {
3972
+ size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
3973
+ DEBUGLOG(5, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
3974
+ if ( ZSTD_isError(flushMin)
3975
+ || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
3976
+ ZSTD_startNewCompression(cctx);
3977
+ }
3978
+ return flushMin;
3979
+ }
3980
+ #endif
3981
+
3982
+ CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
3983
+ DEBUGLOG(5, "completed ZSTD_compress_generic");
3984
+ return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
3985
+ }
3986
+
3987
+ size_t ZSTD_compress_generic_simpleArgs (
3988
+ ZSTD_CCtx* cctx,
3989
+ void* dst, size_t dstCapacity, size_t* dstPos,
3990
+ const void* src, size_t srcSize, size_t* srcPos,
3991
+ ZSTD_EndDirective endOp)
3992
+ {
3993
+ ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
3994
+ ZSTD_inBuffer input = { src, srcSize, *srcPos };
3995
+ /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
3996
+ size_t const cErr = ZSTD_compress_generic(cctx, &output, &input, endOp);
3997
+ *dstPos = output.pos;
3998
+ *srcPos = input.pos;
3999
+ return cErr;
3395
4000
  }
3396
4001
 
3397
4002
 
@@ -3401,89 +4006,59 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
3401
4006
  * @return : amount of data remaining to flush */
3402
4007
  size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
3403
4008
  {
3404
- size_t srcSize = 0;
3405
- size_t sizeWritten = output->size - output->pos;
3406
- size_t const result = ZSTD_compressStream_generic(zcs,
3407
- (char*)(output->dst) + output->pos, &sizeWritten,
3408
- &srcSize, &srcSize, /* use a valid src address instead of NULL */
3409
- zsf_flush);
3410
- output->pos += sizeWritten;
3411
- if (ZSTD_isError(result)) return result;
3412
- return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */
4009
+ ZSTD_inBuffer input = { NULL, 0, 0 };
4010
+ if (output->pos > output->size) return ERROR(GENERIC);
4011
+ CHECK_F( ZSTD_compressStream_generic(zcs, output, &input, ZSTD_e_flush) );
4012
+ return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */
3413
4013
  }
3414
4014
 
3415
4015
 
3416
4016
  size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
3417
4017
  {
3418
- BYTE* const ostart = (BYTE*)(output->dst) + output->pos;
3419
- BYTE* const oend = (BYTE*)(output->dst) + output->size;
3420
- BYTE* op = ostart;
3421
-
3422
- if (zcs->stage != zcss_final) {
3423
- /* flush whatever remains */
3424
- size_t srcSize = 0;
3425
- size_t sizeWritten = output->size - output->pos;
3426
- size_t const notEnded = ZSTD_compressStream_generic(zcs, ostart, &sizeWritten,
3427
- &srcSize /* use a valid src address instead of NULL */, &srcSize, zsf_end);
3428
- size_t const remainingToFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
3429
- op += sizeWritten;
3430
- if (remainingToFlush) {
3431
- output->pos += sizeWritten;
3432
- return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */ + (zcs->checksum * 4);
3433
- }
3434
- /* create epilogue */
3435
- zcs->stage = zcss_final;
3436
- zcs->outBuffContentSize = !notEnded ? 0 :
3437
- /* write epilogue, including final empty block, into outBuff */
3438
- ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0);
3439
- if (ZSTD_isError(zcs->outBuffContentSize)) return zcs->outBuffContentSize;
3440
- }
3441
-
3442
- /* flush epilogue */
3443
- { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
3444
- size_t const flushed = ZSTD_limitCopy(op, oend-op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
3445
- op += flushed;
3446
- zcs->outBuffFlushedSize += flushed;
3447
- output->pos += op-ostart;
3448
- if (toFlush==flushed) zcs->stage = zcss_init; /* end reached */
3449
- return toFlush - flushed;
4018
+ ZSTD_inBuffer input = { NULL, 0, 0 };
4019
+ if (output->pos > output->size) return ERROR(GENERIC);
4020
+ CHECK_F( ZSTD_compressStream_generic(zcs, output, &input, ZSTD_e_end) );
4021
+ { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
4022
+ size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4;
4023
+ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize + lastBlockSize + checksumSize;
4024
+ DEBUGLOG(5, "ZSTD_endStream : remaining to flush : %u",
4025
+ (unsigned)toFlush);
4026
+ return toFlush;
3450
4027
  }
3451
4028
  }
3452
4029
 
3453
4030
 
3454
-
3455
4031
  /*-===== Pre-defined compression levels =====-*/
3456
4032
 
3457
- #define ZSTD_DEFAULT_CLEVEL 1
3458
4033
  #define ZSTD_MAX_CLEVEL 22
3459
4034
  int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
3460
4035
 
3461
4036
  static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
3462
- { /* "default" */
4037
+ { /* "default" - guarantees a monotonically increasing memory budget */
3463
4038
  /* W, C, H, S, L, TL, strat */
3464
4039
  { 18, 12, 12, 1, 7, 16, ZSTD_fast }, /* level 0 - never used */
3465
4040
  { 19, 13, 14, 1, 7, 16, ZSTD_fast }, /* level 1 */
3466
4041
  { 19, 15, 16, 1, 6, 16, ZSTD_fast }, /* level 2 */
3467
- { 20, 16, 17, 1, 5, 16, ZSTD_dfast }, /* level 3.*/
3468
- { 20, 18, 18, 1, 5, 16, ZSTD_dfast }, /* level 4.*/
3469
- { 20, 15, 18, 3, 5, 16, ZSTD_greedy }, /* level 5 */
3470
- { 21, 16, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
3471
- { 21, 17, 20, 3, 5, 16, ZSTD_lazy }, /* level 7 */
4042
+ { 20, 16, 17, 1, 5, 16, ZSTD_dfast }, /* level 3 */
4043
+ { 20, 17, 18, 1, 5, 16, ZSTD_dfast }, /* level 4 */
4044
+ { 20, 17, 18, 2, 5, 16, ZSTD_greedy }, /* level 5 */
4045
+ { 21, 17, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
4046
+ { 21, 18, 19, 3, 5, 16, ZSTD_lazy }, /* level 7 */
3472
4047
  { 21, 18, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
3473
- { 21, 20, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 9 */
4048
+ { 21, 19, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 9 */
3474
4049
  { 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
3475
4050
  { 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
3476
4051
  { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
3477
4052
  { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 13 */
3478
4053
  { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 14 */
3479
- { 22, 21, 21, 5, 5, 16, ZSTD_btlazy2 }, /* level 15 */
4054
+ { 22, 21, 22, 5, 5, 16, ZSTD_btlazy2 }, /* level 15 */
3480
4055
  { 23, 22, 22, 5, 5, 16, ZSTD_btlazy2 }, /* level 16 */
3481
- { 23, 21, 22, 4, 5, 24, ZSTD_btopt }, /* level 17 */
4056
+ { 23, 22, 22, 4, 5, 24, ZSTD_btopt }, /* level 17 */
3482
4057
  { 23, 22, 22, 5, 4, 32, ZSTD_btopt }, /* level 18 */
3483
4058
  { 23, 23, 22, 6, 3, 48, ZSTD_btopt }, /* level 19 */
3484
- { 25, 25, 23, 7, 3, 64, ZSTD_btopt2 }, /* level 20 */
3485
- { 26, 26, 23, 7, 3,256, ZSTD_btopt2 }, /* level 21 */
3486
- { 27, 27, 25, 9, 3,512, ZSTD_btopt2 }, /* level 22 */
4059
+ { 25, 25, 23, 7, 3, 64, ZSTD_btultra }, /* level 20 */
4060
+ { 26, 26, 24, 7, 3,256, ZSTD_btultra }, /* level 21 */
4061
+ { 27, 27, 25, 9, 3,512, ZSTD_btultra }, /* level 22 */
3487
4062
  },
3488
4063
  { /* for srcSize <= 256 KB */
3489
4064
  /* W, C, H, S, L, T, strat */
@@ -3507,9 +4082,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3507
4082
  { 18, 19, 18, 8, 3, 64, ZSTD_btopt }, /* level 17.*/
3508
4083
  { 18, 19, 18, 9, 3,128, ZSTD_btopt }, /* level 18.*/
3509
4084
  { 18, 19, 18, 10, 3,256, ZSTD_btopt }, /* level 19.*/
3510
- { 18, 19, 18, 11, 3,512, ZSTD_btopt2 }, /* level 20.*/
3511
- { 18, 19, 18, 12, 3,512, ZSTD_btopt2 }, /* level 21.*/
3512
- { 18, 19, 18, 13, 3,512, ZSTD_btopt2 }, /* level 22.*/
4085
+ { 18, 19, 18, 11, 3,512, ZSTD_btultra }, /* level 20.*/
4086
+ { 18, 19, 18, 12, 3,512, ZSTD_btultra }, /* level 21.*/
4087
+ { 18, 19, 18, 13, 3,512, ZSTD_btultra }, /* level 22.*/
3513
4088
  },
3514
4089
  { /* for srcSize <= 128 KB */
3515
4090
  /* W, C, H, S, L, T, strat */
@@ -3533,9 +4108,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3533
4108
  { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
3534
4109
  { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
3535
4110
  { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
3536
- { 17, 18, 17, 9, 3,256, ZSTD_btopt2 }, /* level 20.*/
3537
- { 17, 18, 17, 10, 3,256, ZSTD_btopt2 }, /* level 21.*/
3538
- { 17, 18, 17, 11, 3,512, ZSTD_btopt2 }, /* level 22.*/
4111
+ { 17, 18, 17, 9, 3,256, ZSTD_btultra }, /* level 20.*/
4112
+ { 17, 18, 17, 10, 3,256, ZSTD_btultra }, /* level 21.*/
4113
+ { 17, 18, 17, 11, 3,512, ZSTD_btultra }, /* level 22.*/
3539
4114
  },
3540
4115
  { /* for srcSize <= 16 KB */
3541
4116
  /* W, C, H, S, L, T, strat */
@@ -3559,39 +4134,59 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
3559
4134
  { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
3560
4135
  { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
3561
4136
  { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
3562
- { 14, 15, 15, 8, 3,256, ZSTD_btopt2 }, /* level 20.*/
3563
- { 14, 15, 15, 9, 3,256, ZSTD_btopt2 }, /* level 21.*/
3564
- { 14, 15, 15, 10, 3,256, ZSTD_btopt2 }, /* level 22.*/
4137
+ { 14, 15, 15, 8, 3,256, ZSTD_btultra }, /* level 20.*/
4138
+ { 14, 15, 15, 9, 3,256, ZSTD_btultra }, /* level 21.*/
4139
+ { 14, 15, 15, 10, 3,256, ZSTD_btultra }, /* level 22.*/
3565
4140
  },
3566
4141
  };
3567
4142
 
4143
+ #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
4144
+ /* This function just controls
4145
+ * the monotonic memory budget increase of ZSTD_defaultCParameters[0].
4146
+ * Run once, on first ZSTD_getCParams() usage, if ZSTD_DEBUG is enabled
4147
+ */
4148
+ MEM_STATIC void ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget(void)
4149
+ {
4150
+ int level;
4151
+ for (level=1; level<ZSTD_maxCLevel(); level++) {
4152
+ ZSTD_compressionParameters const c1 = ZSTD_defaultCParameters[0][level];
4153
+ ZSTD_compressionParameters const c2 = ZSTD_defaultCParameters[0][level+1];
4154
+ assert(c1.windowLog <= c2.windowLog);
4155
+ # define ZSTD_TABLECOST(h,c) ((1<<(h)) + (1<<(c)))
4156
+ assert(ZSTD_TABLECOST(c1.hashLog, c1.chainLog) <= ZSTD_TABLECOST(c2.hashLog, c2.chainLog));
4157
+ }
4158
+ }
4159
+ #endif
4160
+
3568
4161
  /*! ZSTD_getCParams() :
3569
4162
  * @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`.
3570
4163
  * Size values are optional, provide 0 if not known or unused */
3571
- ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSize, size_t dictSize)
4164
+ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
3572
4165
  {
3573
- ZSTD_compressionParameters cp;
3574
- size_t const addedSize = srcSize ? 0 : 500;
3575
- U64 const rSize = srcSize+dictSize ? srcSize+dictSize+addedSize : (U64)-1;
4166
+ size_t const addedSize = srcSizeHint ? 0 : 500;
4167
+ U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
3576
4168
  U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
3577
- if (compressionLevel <= 0) compressionLevel = ZSTD_DEFAULT_CLEVEL; /* 0 == default; no negative compressionLevel yet */
3578
- if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
3579
- cp = ZSTD_defaultCParameters[tableID][compressionLevel];
3580
- if (MEM_32bits()) { /* auto-correction, for 32-bits mode */
3581
- if (cp.windowLog > ZSTD_WINDOWLOG_MAX) cp.windowLog = ZSTD_WINDOWLOG_MAX;
3582
- if (cp.chainLog > ZSTD_CHAINLOG_MAX) cp.chainLog = ZSTD_CHAINLOG_MAX;
3583
- if (cp.hashLog > ZSTD_HASHLOG_MAX) cp.hashLog = ZSTD_HASHLOG_MAX;
4169
+
4170
+ #if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
4171
+ static int g_monotonicTest = 1;
4172
+ if (g_monotonicTest) {
4173
+ ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget();
4174
+ g_monotonicTest=0;
3584
4175
  }
3585
- cp = ZSTD_adjustCParams(cp, srcSize, dictSize);
3586
- return cp;
4176
+ #endif
4177
+
4178
+ if (compressionLevel <= 0) compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default; no negative compressionLevel yet */
4179
+ if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
4180
+ { ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
4181
+ return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
3587
4182
  }
3588
4183
 
3589
4184
  /*! ZSTD_getParams() :
3590
4185
  * same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`).
3591
4186
  * All fields of `ZSTD_frameParameters` are set to default (0) */
3592
- ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) {
4187
+ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
3593
4188
  ZSTD_parameters params;
3594
- ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize);
4189
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
3595
4190
  memset(&params, 0, sizeof(params));
3596
4191
  params.cParams = cParams;
3597
4192
  return params;