zstd-ruby 1.2.0.0 → 1.3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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;