zstd-ruby 1.3.5.0 → 1.3.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -2
  3. data/README.md +2 -1
  4. data/ext/zstdruby/libzstd/BUCK +1 -0
  5. data/ext/zstdruby/libzstd/Makefile +25 -13
  6. data/ext/zstdruby/libzstd/README.md +11 -10
  7. data/ext/zstdruby/libzstd/common/bitstream.h +8 -11
  8. data/ext/zstdruby/libzstd/common/compiler.h +30 -8
  9. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  10. data/ext/zstdruby/libzstd/common/mem.h +20 -2
  11. data/ext/zstdruby/libzstd/common/xxhash.c +1 -0
  12. data/ext/zstdruby/libzstd/common/zstd_internal.h +3 -2
  13. data/ext/zstdruby/libzstd/compress/fse_compress.c +55 -48
  14. data/ext/zstdruby/libzstd/compress/hist.h +1 -1
  15. data/ext/zstdruby/libzstd/compress/huf_compress.c +1 -1
  16. data/ext/zstdruby/libzstd/compress/zstd_compress.c +290 -147
  17. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +5 -2
  18. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +63 -51
  19. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -4
  20. data/ext/zstdruby/libzstd/compress/zstd_fast.c +44 -33
  21. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -4
  22. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +125 -116
  23. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +13 -15
  24. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +9 -11
  25. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +0 -1
  26. data/ext/zstdruby/libzstd/compress/zstd_opt.c +42 -36
  27. data/ext/zstdruby/libzstd/compress/zstd_opt.h +8 -9
  28. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +96 -51
  29. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +16 -6
  30. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +3 -3
  31. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +169 -101
  32. data/ext/zstdruby/libzstd/dictBuilder/cover.c +111 -87
  33. data/ext/zstdruby/libzstd/dictBuilder/cover.h +83 -0
  34. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +3 -3
  35. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +728 -0
  36. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +34 -31
  37. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +60 -5
  38. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +9 -3
  39. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +6 -0
  40. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +6 -0
  41. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -5
  42. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +12 -9
  43. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +10 -10
  44. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +20 -18
  45. data/ext/zstdruby/libzstd/zstd.h +109 -50
  46. data/lib/zstd-ruby/version.rb +1 -1
  47. metadata +4 -2
@@ -50,7 +50,7 @@
50
50
  size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
51
51
  const void* src, size_t srcSize);
52
52
 
53
- unsigned HIST_isError(size_t code); /*< tells if a return value is an error code */
53
+ unsigned HIST_isError(size_t code); /**< tells if a return value is an error code */
54
54
 
55
55
 
56
56
  /* --- advanced histogram functions --- */
@@ -82,7 +82,7 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
82
82
  * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
83
83
  */
84
84
  #define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
85
- size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
85
+ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
86
86
  {
87
87
  BYTE* const ostart = (BYTE*) dst;
88
88
  BYTE* op = ostart;
@@ -46,7 +46,6 @@ struct ZSTD_CDict_s {
46
46
  size_t workspaceSize;
47
47
  ZSTD_matchState_t matchState;
48
48
  ZSTD_compressedBlockState_t cBlockState;
49
- ZSTD_compressionParameters cParams;
50
49
  ZSTD_customMem customMem;
51
50
  U32 dictID;
52
51
  }; /* typedef'd to ZSTD_CDict within "zstd.h" */
@@ -679,6 +678,9 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
679
678
  CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
680
679
  CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
681
680
  CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
681
+ ZSTD_STATIC_ASSERT(ZSTD_TARGETLENGTH_MIN == 0);
682
+ if (cParams.targetLength > ZSTD_TARGETLENGTH_MAX)
683
+ return ERROR(parameter_outOfBound);
682
684
  if ((U32)(cParams.strategy) > (U32)ZSTD_btultra)
683
685
  return ERROR(parameter_unsupported);
684
686
  return 0;
@@ -699,6 +701,9 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
699
701
  CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
700
702
  CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
701
703
  CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
704
+ ZSTD_STATIC_ASSERT(ZSTD_TARGETLENGTH_MIN == 0);
705
+ if (cParams.targetLength > ZSTD_TARGETLENGTH_MAX)
706
+ cParams.targetLength = ZSTD_TARGETLENGTH_MAX;
702
707
  CLAMP(cParams.strategy, ZSTD_fast, ZSTD_btultra);
703
708
  return cParams;
704
709
  }
@@ -805,7 +810,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
805
810
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
806
811
  U32 const divider = (cParams.searchLength==3) ? 3 : 4;
807
812
  size_t const maxNbSeq = blockSize / divider;
808
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
813
+ size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
809
814
  size_t const entropySpace = HUF_WORKSPACE_SIZE;
810
815
  size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
811
816
  size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
@@ -900,9 +905,27 @@ ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)
900
905
  fp.ingested = cctx->consumedSrcSize + buffered;
901
906
  fp.consumed = cctx->consumedSrcSize;
902
907
  fp.produced = cctx->producedCSize;
908
+ fp.flushed = cctx->producedCSize; /* simplified; some data might still be left within streaming output buffer */
909
+ fp.currentJobID = 0;
910
+ fp.nbActiveWorkers = 0;
903
911
  return fp;
904
912
  } }
905
913
 
914
+ /*! ZSTD_toFlushNow()
915
+ * Only useful for multithreading scenarios currently (nbWorkers >= 1).
916
+ */
917
+ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
918
+ {
919
+ #ifdef ZSTD_MULTITHREAD
920
+ if (cctx->appliedParams.nbWorkers > 0) {
921
+ return ZSTDMT_toFlushNow(cctx->mtctx);
922
+ }
923
+ #endif
924
+ (void)cctx;
925
+ return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */
926
+ }
927
+
928
+
906
929
 
907
930
  static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
908
931
  ZSTD_compressionParameters cParams2)
@@ -913,6 +936,20 @@ static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
913
936
  & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
914
937
  }
915
938
 
939
+ static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
940
+ ZSTD_compressionParameters cParams2)
941
+ {
942
+ (void)cParams1;
943
+ (void)cParams2;
944
+ assert(cParams1.windowLog == cParams2.windowLog);
945
+ assert(cParams1.chainLog == cParams2.chainLog);
946
+ assert(cParams1.hashLog == cParams2.hashLog);
947
+ assert(cParams1.searchLog == cParams2.searchLog);
948
+ assert(cParams1.searchLength == cParams2.searchLength);
949
+ assert(cParams1.targetLength == cParams2.targetLength);
950
+ assert(cParams1.strategy == cParams2.strategy);
951
+ }
952
+
916
953
  /** The parameters are equivalent if ldm is not enabled in both sets or
917
954
  * all the parameters are equivalent. */
918
955
  static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
@@ -931,33 +968,51 @@ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
931
968
  /* ZSTD_sufficientBuff() :
932
969
  * check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
933
970
  * Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
934
- static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t blockSize1,
971
+ static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
972
+ size_t maxNbLit1,
935
973
  ZSTD_buffered_policy_e buffPol2,
936
974
  ZSTD_compressionParameters cParams2,
937
975
  U64 pledgedSrcSize)
938
976
  {
939
977
  size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
940
978
  size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
979
+ size_t const maxNbSeq2 = blockSize2 / ((cParams2.searchLength == 3) ? 3 : 4);
980
+ size_t const maxNbLit2 = blockSize2;
941
981
  size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
942
- DEBUGLOG(4, "ZSTD_sufficientBuff: is windowSize2=%u <= wlog1=%u",
943
- (U32)windowSize2, cParams2.windowLog);
944
- DEBUGLOG(4, "ZSTD_sufficientBuff: is blockSize2=%u <= blockSize1=%u",
945
- (U32)blockSize2, (U32)blockSize1);
946
- return (blockSize2 <= blockSize1) /* seqStore space depends on blockSize */
982
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
983
+ (U32)neededBufferSize2, (U32)bufferSize1);
984
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
985
+ (U32)maxNbSeq2, (U32)maxNbSeq1);
986
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
987
+ (U32)maxNbLit2, (U32)maxNbLit1);
988
+ return (maxNbLit2 <= maxNbLit1)
989
+ & (maxNbSeq2 <= maxNbSeq1)
947
990
  & (neededBufferSize2 <= bufferSize1);
948
991
  }
949
992
 
950
993
  /** Equivalence for resetCCtx purposes */
951
994
  static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
952
995
  ZSTD_CCtx_params params2,
953
- size_t buffSize1, size_t blockSize1,
996
+ size_t buffSize1,
997
+ size_t maxNbSeq1, size_t maxNbLit1,
954
998
  ZSTD_buffered_policy_e buffPol2,
955
999
  U64 pledgedSrcSize)
956
1000
  {
957
1001
  DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
958
- return ZSTD_equivalentCParams(params1.cParams, params2.cParams) &&
959
- ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams) &&
960
- ZSTD_sufficientBuff(buffSize1, blockSize1, buffPol2, params2.cParams, pledgedSrcSize);
1002
+ if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
1003
+ DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
1004
+ return 0;
1005
+ }
1006
+ if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
1007
+ DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
1008
+ return 0;
1009
+ }
1010
+ if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
1011
+ params2.cParams, pledgedSrcSize)) {
1012
+ DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
1013
+ return 0;
1014
+ }
1015
+ return 1;
961
1016
  }
962
1017
 
963
1018
  static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
@@ -996,6 +1051,7 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl
996
1051
 
997
1052
  cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
998
1053
  cctx->appliedParams = params;
1054
+ cctx->blockState.matchState.cParams = params.cParams;
999
1055
  cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
1000
1056
  cctx->consumedSrcSize = 0;
1001
1057
  cctx->producedCSize = 0;
@@ -1032,6 +1088,9 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1032
1088
 
1033
1089
  ms->hashLog3 = hashLog3;
1034
1090
  memset(&ms->window, 0, sizeof(ms->window));
1091
+ ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
1092
+ ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
1093
+ ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
1035
1094
  ZSTD_invalidateMatchState(ms);
1036
1095
 
1037
1096
  /* opt parser space */
@@ -1057,6 +1116,8 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
1057
1116
  ms->hashTable3 = ms->chainTable + chainSize;
1058
1117
  ptr = ms->hashTable3 + h3Size;
1059
1118
 
1119
+ ms->cParams = *cParams;
1120
+
1060
1121
  assert(((size_t)ptr & 3) == 0);
1061
1122
  return ptr;
1062
1123
  }
@@ -1082,8 +1143,9 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1082
1143
 
1083
1144
  if (crp == ZSTDcrp_continue) {
1084
1145
  if (ZSTD_equivalentParams(zc->appliedParams, params,
1085
- zc->inBuffSize, zc->blockSize,
1086
- zbuff, pledgedSrcSize)) {
1146
+ zc->inBuffSize,
1147
+ zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
1148
+ zbuff, pledgedSrcSize)) {
1087
1149
  DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
1088
1150
  zc->appliedParams.cParams.windowLog, zc->blockSize);
1089
1151
  zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
@@ -1104,7 +1166,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1104
1166
  size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
1105
1167
  U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
1106
1168
  size_t const maxNbSeq = blockSize / divider;
1107
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
1169
+ size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
1108
1170
  size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
1109
1171
  size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
1110
1172
  size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
@@ -1144,7 +1206,6 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1144
1206
  if (zc->workSpace == NULL) return ERROR(memory_allocation);
1145
1207
  zc->workSpaceSize = neededSpace;
1146
1208
  zc->workSpaceOversizedDuration = 0;
1147
- ptr = zc->workSpace;
1148
1209
 
1149
1210
  /* Statically sized space.
1150
1211
  * entropyWorkspace never moves,
@@ -1159,6 +1220,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1159
1220
 
1160
1221
  /* init params */
1161
1222
  zc->appliedParams = params;
1223
+ zc->blockState.matchState.cParams = params.cParams;
1162
1224
  zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
1163
1225
  zc->consumedSrcSize = 0;
1164
1226
  zc->producedCSize = 0;
@@ -1195,13 +1257,18 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
1195
1257
  ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
1196
1258
 
1197
1259
  /* sequences storage */
1260
+ zc->seqStore.maxNbSeq = maxNbSeq;
1198
1261
  zc->seqStore.sequencesStart = (seqDef*)ptr;
1199
1262
  ptr = zc->seqStore.sequencesStart + maxNbSeq;
1200
1263
  zc->seqStore.llCode = (BYTE*) ptr;
1201
1264
  zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
1202
1265
  zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
1203
1266
  zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
1204
- ptr = zc->seqStore.litStart + blockSize;
1267
+ /* ZSTD_wildcopy() is used to copy into the literals buffer,
1268
+ * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
1269
+ */
1270
+ zc->seqStore.maxNbLit = blockSize;
1271
+ ptr = zc->seqStore.litStart + blockSize + WILDCOPY_OVERLENGTH;
1205
1272
 
1206
1273
  /* ldm bucketOffsets table */
1207
1274
  if (params.ldmParams.enableLdm) {
@@ -1235,54 +1302,59 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
1235
1302
  assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
1236
1303
  }
1237
1304
 
1238
- static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1239
- const ZSTD_CDict* cdict,
1240
- ZSTD_CCtx_params params,
1241
- U64 pledgedSrcSize,
1242
- ZSTD_buffered_policy_e zbuff)
1243
- {
1244
- /* We have a choice between copying the dictionary context into the working
1245
- * context, or referencing the dictionary context from the working context
1246
- * in-place. We decide here which strategy to use. */
1247
- const U64 attachDictSizeCutoffs[(unsigned)ZSTD_btultra+1] = {
1248
- 8 KB, /* unused */
1249
- 8 KB, /* ZSTD_fast */
1250
- 16 KB, /* ZSTD_dfast */
1251
- 32 KB, /* ZSTD_greedy */
1252
- 32 KB, /* ZSTD_lazy */
1253
- 32 KB, /* ZSTD_lazy2 */
1254
- 32 KB, /* ZSTD_btlazy2 */
1255
- 32 KB, /* ZSTD_btopt */
1256
- 8 KB /* ZSTD_btultra */
1257
- };
1258
- const int attachDict = ( pledgedSrcSize <= attachDictSizeCutoffs[cdict->cParams.strategy]
1259
- || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1260
- || params.attachDictPref == ZSTD_dictForceAttach )
1261
- && params.attachDictPref != ZSTD_dictForceCopy
1262
- && !params.forceWindow /* dictMatchState isn't correctly
1263
- * handled in _enforceMaxDist */
1264
- && ZSTD_equivalentCParams(cctx->appliedParams.cParams,
1265
- cdict->cParams);
1266
-
1267
- DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
1305
+ /* These are the approximate sizes for each strategy past which copying the
1306
+ * dictionary tables into the working context is faster than using them
1307
+ * in-place.
1308
+ */
1309
+ static const size_t attachDictSizeCutoffs[(unsigned)ZSTD_btultra+1] = {
1310
+ 8 KB, /* unused */
1311
+ 8 KB, /* ZSTD_fast */
1312
+ 16 KB, /* ZSTD_dfast */
1313
+ 32 KB, /* ZSTD_greedy */
1314
+ 32 KB, /* ZSTD_lazy */
1315
+ 32 KB, /* ZSTD_lazy2 */
1316
+ 32 KB, /* ZSTD_btlazy2 */
1317
+ 32 KB, /* ZSTD_btopt */
1318
+ 8 KB /* ZSTD_btultra */
1319
+ };
1268
1320
 
1321
+ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
1322
+ ZSTD_CCtx_params params,
1323
+ U64 pledgedSrcSize)
1324
+ {
1325
+ size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
1326
+ return ( pledgedSrcSize <= cutoff
1327
+ || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
1328
+ || params.attachDictPref == ZSTD_dictForceAttach )
1329
+ && params.attachDictPref != ZSTD_dictForceCopy
1330
+ && !params.forceWindow; /* dictMatchState isn't correctly
1331
+ * handled in _enforceMaxDist */
1332
+ }
1269
1333
 
1270
- { unsigned const windowLog = params.cParams.windowLog;
1334
+ static size_t ZSTD_resetCCtx_byAttachingCDict(
1335
+ ZSTD_CCtx* cctx,
1336
+ const ZSTD_CDict* cdict,
1337
+ ZSTD_CCtx_params params,
1338
+ U64 pledgedSrcSize,
1339
+ ZSTD_buffered_policy_e zbuff)
1340
+ {
1341
+ {
1342
+ const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1343
+ unsigned const windowLog = params.cParams.windowLog;
1271
1344
  assert(windowLog != 0);
1272
- /* Copy only compression parameters related to tables. */
1273
- params.cParams = cdict->cParams;
1345
+ /* Resize working context table params for input only, since the dict
1346
+ * has its own tables. */
1347
+ params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
1274
1348
  params.cParams.windowLog = windowLog;
1275
1349
  ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1276
- attachDict ? ZSTDcrp_continue : ZSTDcrp_noMemset,
1277
- zbuff);
1278
- assert(cctx->appliedParams.cParams.strategy == cdict->cParams.strategy);
1279
- assert(cctx->appliedParams.cParams.hashLog == cdict->cParams.hashLog);
1280
- assert(cctx->appliedParams.cParams.chainLog == cdict->cParams.chainLog);
1350
+ ZSTDcrp_continue, zbuff);
1351
+ assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1281
1352
  }
1282
1353
 
1283
- if (attachDict) {
1284
- const U32 cdictLen = (U32)( cdict->matchState.window.nextSrc
1354
+ {
1355
+ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
1285
1356
  - cdict->matchState.window.base);
1357
+ const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
1286
1358
  if (cdictLen == 0) {
1287
1359
  /* don't even attach dictionaries with no contents */
1288
1360
  DEBUGLOG(4, "skipping attaching empty dictionary");
@@ -1292,41 +1364,69 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1292
1364
 
1293
1365
  /* prep working match state so dict matches never have negative indices
1294
1366
  * when they are translated to the working context's index space. */
1295
- if (cctx->blockState.matchState.window.dictLimit < cdictLen) {
1367
+ if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {
1296
1368
  cctx->blockState.matchState.window.nextSrc =
1297
- cctx->blockState.matchState.window.base + cdictLen;
1369
+ cctx->blockState.matchState.window.base + cdictEnd;
1298
1370
  ZSTD_window_clear(&cctx->blockState.matchState.window);
1299
1371
  }
1300
1372
  cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
1301
1373
  }
1302
- } else {
1303
- DEBUGLOG(4, "copying dictionary into context");
1304
- /* copy tables */
1305
- { size_t const chainSize = (cdict->cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict->cParams.chainLog);
1306
- size_t const hSize = (size_t)1 << cdict->cParams.hashLog;
1307
- size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1308
- assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1309
- assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1310
- assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1311
- assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1312
- memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1313
- }
1374
+ }
1314
1375
 
1315
- /* Zero the hashTable3, since the cdict never fills it */
1316
- { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
1317
- assert(cdict->matchState.hashLog3 == 0);
1318
- memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1319
- }
1376
+ cctx->dictID = cdict->dictID;
1320
1377
 
1321
- /* copy dictionary offsets */
1322
- {
1323
- ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1324
- ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1325
- dstMatchState->window = srcMatchState->window;
1326
- dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1327
- dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1328
- dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1329
- }
1378
+ /* copy block state */
1379
+ memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
1380
+
1381
+ return 0;
1382
+ }
1383
+
1384
+ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
1385
+ const ZSTD_CDict* cdict,
1386
+ ZSTD_CCtx_params params,
1387
+ U64 pledgedSrcSize,
1388
+ ZSTD_buffered_policy_e zbuff)
1389
+ {
1390
+ const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
1391
+
1392
+ DEBUGLOG(4, "copying dictionary into context");
1393
+
1394
+ { unsigned const windowLog = params.cParams.windowLog;
1395
+ assert(windowLog != 0);
1396
+ /* Copy only compression parameters related to tables. */
1397
+ params.cParams = *cdict_cParams;
1398
+ params.cParams.windowLog = windowLog;
1399
+ ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
1400
+ ZSTDcrp_noMemset, zbuff);
1401
+ assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
1402
+ assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
1403
+ assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
1404
+ }
1405
+
1406
+ /* copy tables */
1407
+ { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
1408
+ size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
1409
+ size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
1410
+ assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
1411
+ assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
1412
+ assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
1413
+ assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
1414
+ memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
1415
+ }
1416
+
1417
+ /* Zero the hashTable3, since the cdict never fills it */
1418
+ { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
1419
+ assert(cdict->matchState.hashLog3 == 0);
1420
+ memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
1421
+ }
1422
+
1423
+ /* copy dictionary offsets */
1424
+ { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
1425
+ ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
1426
+ dstMatchState->window = srcMatchState->window;
1427
+ dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
1428
+ dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
1429
+ dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
1330
1430
  }
1331
1431
 
1332
1432
  cctx->dictID = cdict->dictID;
@@ -1337,6 +1437,27 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1337
1437
  return 0;
1338
1438
  }
1339
1439
 
1440
+ /* We have a choice between copying the dictionary context into the working
1441
+ * context, or referencing the dictionary context from the working context
1442
+ * in-place. We decide here which strategy to use. */
1443
+ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
1444
+ const ZSTD_CDict* cdict,
1445
+ ZSTD_CCtx_params params,
1446
+ U64 pledgedSrcSize,
1447
+ ZSTD_buffered_policy_e zbuff)
1448
+ {
1449
+
1450
+ DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
1451
+
1452
+ if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
1453
+ return ZSTD_resetCCtx_byAttachingCDict(
1454
+ cctx, cdict, params, pledgedSrcSize, zbuff);
1455
+ } else {
1456
+ return ZSTD_resetCCtx_byCopyingCDict(
1457
+ cctx, cdict, params, pledgedSrcSize, zbuff);
1458
+ }
1459
+ }
1460
+
1340
1461
  /*! ZSTD_copyCCtx_internal() :
1341
1462
  * Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
1342
1463
  * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
@@ -1481,15 +1602,15 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
1481
1602
 
1482
1603
  /* See doc/zstd_compression_format.md for detailed format description */
1483
1604
 
1484
- size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1605
+ static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
1485
1606
  {
1607
+ U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
1486
1608
  if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
1609
+ MEM_writeLE24(dst, cBlockHeader24);
1487
1610
  memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
1488
- MEM_writeLE24(dst, (U32)(srcSize << 2) + (U32)bt_raw);
1489
- return ZSTD_blockHeaderSize+srcSize;
1611
+ return ZSTD_blockHeaderSize + srcSize;
1490
1612
  }
1491
1613
 
1492
-
1493
1614
  static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1494
1615
  {
1495
1616
  BYTE* const ostart = (BYTE* const)dst;
@@ -1644,6 +1765,7 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
1644
1765
  BYTE* const mlCodeTable = seqStorePtr->mlCode;
1645
1766
  U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
1646
1767
  U32 u;
1768
+ assert(nbSeq <= seqStorePtr->maxNbSeq);
1647
1769
  for (u=0; u<nbSeq; u++) {
1648
1770
  U32 const llv = sequences[u].litLength;
1649
1771
  U32 const mlv = sequences[u].matchLength;
@@ -2040,7 +2162,7 @@ ZSTD_encodeSequences_bmi2(
2040
2162
 
2041
2163
  #endif
2042
2164
 
2043
- size_t ZSTD_encodeSequences(
2165
+ static size_t ZSTD_encodeSequences(
2044
2166
  void* dst, size_t dstCapacity,
2045
2167
  FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
2046
2168
  FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
@@ -2232,13 +2354,6 @@ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
2232
2354
  if (cSize >= maxCSize) return 0; /* block not compressed */
2233
2355
  }
2234
2356
 
2235
- /* We check that dictionaries have offset codes available for the first
2236
- * block. After the first block, the offcode table might not have large
2237
- * enough codes to represent the offsets in the data.
2238
- */
2239
- if (nextEntropy->fse.offcode_repeatMode == FSE_repeat_valid)
2240
- nextEntropy->fse.offcode_repeatMode = FSE_repeat_check;
2241
-
2242
2357
  return cSize;
2243
2358
  }
2244
2359
 
@@ -2305,12 +2420,18 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2305
2420
  const void* src, size_t srcSize)
2306
2421
  {
2307
2422
  ZSTD_matchState_t* const ms = &zc->blockState.matchState;
2423
+ size_t cSize;
2308
2424
  DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%zu, dictLimit=%u, nextToUpdate=%u)",
2309
2425
  dstCapacity, ms->window.dictLimit, ms->nextToUpdate);
2426
+ assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
2427
+
2428
+ /* Assert that we have correctly flushed the ctx params into the ms's copy */
2429
+ ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
2310
2430
 
2311
2431
  if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
2312
2432
  ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength);
2313
- return 0; /* don't even attempt compression below a certain srcSize */
2433
+ cSize = 0;
2434
+ goto out; /* don't even attempt compression below a certain srcSize */
2314
2435
  }
2315
2436
  ZSTD_resetSeqStore(&(zc->seqStore));
2316
2437
  ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* required for optimal parser to read stats from dictionary */
@@ -2343,7 +2464,6 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2343
2464
  ZSTD_ldm_blockCompress(&zc->externSeqStore,
2344
2465
  ms, &zc->seqStore,
2345
2466
  zc->blockState.nextCBlock->rep,
2346
- &zc->appliedParams.cParams,
2347
2467
  src, srcSize);
2348
2468
  assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
2349
2469
  } else if (zc->appliedParams.ldmParams.enableLdm) {
@@ -2360,31 +2480,38 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
2360
2480
  ZSTD_ldm_blockCompress(&ldmSeqStore,
2361
2481
  ms, &zc->seqStore,
2362
2482
  zc->blockState.nextCBlock->rep,
2363
- &zc->appliedParams.cParams,
2364
2483
  src, srcSize);
2365
2484
  assert(ldmSeqStore.pos == ldmSeqStore.size);
2366
2485
  } else { /* not long range mode */
2367
2486
  ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
2368
- lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, &zc->appliedParams.cParams, src, srcSize);
2487
+ lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
2369
2488
  }
2370
2489
  { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
2371
2490
  ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
2372
2491
  } }
2373
2492
 
2374
2493
  /* encode sequences and literals */
2375
- { size_t const cSize = ZSTD_compressSequences(&zc->seqStore,
2376
- &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
2377
- &zc->appliedParams,
2378
- dst, dstCapacity,
2379
- srcSize, zc->entropyWorkspace, zc->bmi2);
2380
- if (ZSTD_isError(cSize) || cSize == 0) return cSize;
2381
- /* confirm repcodes and entropy tables */
2382
- { ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
2383
- zc->blockState.prevCBlock = zc->blockState.nextCBlock;
2384
- zc->blockState.nextCBlock = tmp;
2385
- }
2386
- return cSize;
2494
+ cSize = ZSTD_compressSequences(&zc->seqStore,
2495
+ &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
2496
+ &zc->appliedParams,
2497
+ dst, dstCapacity,
2498
+ srcSize, zc->entropyWorkspace, zc->bmi2);
2499
+
2500
+ out:
2501
+ if (!ZSTD_isError(cSize) && cSize != 0) {
2502
+ /* confirm repcodes and entropy tables when emitting a compressed block */
2503
+ ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
2504
+ zc->blockState.prevCBlock = zc->blockState.nextCBlock;
2505
+ zc->blockState.nextCBlock = tmp;
2387
2506
  }
2507
+ /* We check that dictionaries have offset codes available for the first
2508
+ * block. After the first block, the offcode table might not have large
2509
+ * enough codes to represent the offsets in the data.
2510
+ */
2511
+ if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
2512
+ zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
2513
+
2514
+ return cSize;
2388
2515
  }
2389
2516
 
2390
2517
 
@@ -2426,7 +2553,6 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2426
2553
  ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2427
2554
  ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2428
2555
  ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2429
-
2430
2556
  ZSTD_reduceIndex(cctx, correction);
2431
2557
  if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2432
2558
  else ms->nextToUpdate -= correction;
@@ -2442,11 +2568,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
2442
2568
  if (ZSTD_isError(cSize)) return cSize;
2443
2569
 
2444
2570
  if (cSize == 0) { /* block is not compressible */
2445
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(blockSize << 3);
2446
- if (blockSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
2447
- MEM_writeLE32(op, cBlockHeader24); /* 4th byte will be overwritten */
2448
- memcpy(op + ZSTD_blockHeaderSize, ip, blockSize);
2449
- cSize = ZSTD_blockHeaderSize + blockSize;
2571
+ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
2572
+ if (ZSTD_isError(cSize)) return cSize;
2450
2573
  } else {
2451
2574
  U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
2452
2575
  MEM_writeLE24(op, cBlockHeader24);
@@ -2545,7 +2668,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2545
2668
  const void* src, size_t srcSize,
2546
2669
  U32 frame, U32 lastFrameChunk)
2547
2670
  {
2548
- ZSTD_matchState_t* ms = &cctx->blockState.matchState;
2671
+ ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
2549
2672
  size_t fhSize = 0;
2550
2673
 
2551
2674
  DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
@@ -2566,8 +2689,25 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
2566
2689
  if (!ZSTD_window_update(&ms->window, src, srcSize)) {
2567
2690
  ms->nextToUpdate = ms->window.dictLimit;
2568
2691
  }
2569
- if (cctx->appliedParams.ldmParams.enableLdm)
2692
+ if (cctx->appliedParams.ldmParams.enableLdm) {
2570
2693
  ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
2694
+ }
2695
+
2696
+ if (!frame) {
2697
+ /* overflow check and correction for block mode */
2698
+ if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) {
2699
+ U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
2700
+ U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
2701
+ ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
2702
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
2703
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
2704
+ ZSTD_reduceIndex(cctx, correction);
2705
+ if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
2706
+ else ms->nextToUpdate -= correction;
2707
+ ms->loadedDictEnd = 0;
2708
+ ms->dictMatchState = NULL;
2709
+ }
2710
+ }
2571
2711
 
2572
2712
  DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize);
2573
2713
  { size_t const cSize = frame ?
@@ -2609,6 +2749,7 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
2609
2749
  {
2610
2750
  size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
2611
2751
  if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
2752
+
2612
2753
  return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
2613
2754
  }
2614
2755
 
@@ -2622,34 +2763,36 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
2622
2763
  {
2623
2764
  const BYTE* const ip = (const BYTE*) src;
2624
2765
  const BYTE* const iend = ip + srcSize;
2625
- ZSTD_compressionParameters const* cParams = &params->cParams;
2626
2766
 
2627
2767
  ZSTD_window_update(&ms->window, src, srcSize);
2628
2768
  ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
2629
2769
 
2770
+ /* Assert that we the ms params match the params we're being given */
2771
+ ZSTD_assertEqualCParams(params->cParams, ms->cParams);
2772
+
2630
2773
  if (srcSize <= HASH_READ_SIZE) return 0;
2631
2774
 
2632
2775
  switch(params->cParams.strategy)
2633
2776
  {
2634
2777
  case ZSTD_fast:
2635
- ZSTD_fillHashTable(ms, cParams, iend, dtlm);
2778
+ ZSTD_fillHashTable(ms, iend, dtlm);
2636
2779
  break;
2637
2780
  case ZSTD_dfast:
2638
- ZSTD_fillDoubleHashTable(ms, cParams, iend, dtlm);
2781
+ ZSTD_fillDoubleHashTable(ms, iend, dtlm);
2639
2782
  break;
2640
2783
 
2641
2784
  case ZSTD_greedy:
2642
2785
  case ZSTD_lazy:
2643
2786
  case ZSTD_lazy2:
2644
2787
  if (srcSize >= HASH_READ_SIZE)
2645
- ZSTD_insertAndFindFirstIndex(ms, cParams, iend-HASH_READ_SIZE);
2788
+ ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
2646
2789
  break;
2647
2790
 
2648
2791
  case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
2649
2792
  case ZSTD_btopt:
2650
2793
  case ZSTD_btultra:
2651
2794
  if (srcSize >= HASH_READ_SIZE)
2652
- ZSTD_updateTree(ms, cParams, iend-HASH_READ_SIZE, iend);
2795
+ ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
2653
2796
  break;
2654
2797
 
2655
2798
  default:
@@ -2813,13 +2956,13 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
2813
2956
 
2814
2957
  /*! ZSTD_compressBegin_internal() :
2815
2958
  * @return : 0, or an error code */
2816
- size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2817
- const void* dict, size_t dictSize,
2818
- ZSTD_dictContentType_e dictContentType,
2819
- ZSTD_dictTableLoadMethod_e dtlm,
2820
- const ZSTD_CDict* cdict,
2821
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
2822
- ZSTD_buffered_policy_e zbuff)
2959
+ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
2960
+ const void* dict, size_t dictSize,
2961
+ ZSTD_dictContentType_e dictContentType,
2962
+ ZSTD_dictTableLoadMethod_e dtlm,
2963
+ const ZSTD_CDict* cdict,
2964
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
2965
+ ZSTD_buffered_policy_e zbuff)
2823
2966
  {
2824
2967
  DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog);
2825
2968
  /* params are supposed to be fully validated at this point */
@@ -3073,7 +3216,7 @@ static size_t ZSTD_initCDict_internal(
3073
3216
  {
3074
3217
  DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (U32)dictContentType);
3075
3218
  assert(!ZSTD_checkCParams(cParams));
3076
- cdict->cParams = cParams;
3219
+ cdict->matchState.cParams = cParams;
3077
3220
  if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
3078
3221
  cdict->dictBuffer = NULL;
3079
3222
  cdict->dictContent = dictBuffer;
@@ -3227,7 +3370,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
3227
3370
  ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
3228
3371
  {
3229
3372
  assert(cdict != NULL);
3230
- return cdict->cParams;
3373
+ return cdict->matchState.cParams;
3231
3374
  }
3232
3375
 
3233
3376
  /* ZSTD_compressBegin_usingCDict_advanced() :
@@ -3332,9 +3475,11 @@ size_t ZSTD_CStreamOutSize(void)
3332
3475
  static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
3333
3476
  const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
3334
3477
  const ZSTD_CDict* const cdict,
3335
- ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize)
3478
+ ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize)
3336
3479
  {
3337
3480
  DEBUGLOG(4, "ZSTD_resetCStream_internal");
3481
+ /* Finalize the compression parameters */
3482
+ params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
3338
3483
  /* params are supposed to be fully validated at this point */
3339
3484
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3340
3485
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
@@ -3363,7 +3508,6 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
3363
3508
  DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize);
3364
3509
  if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
3365
3510
  params.fParams.contentSizeFlag = 1;
3366
- params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, 0);
3367
3511
  return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
3368
3512
  }
3369
3513
 
@@ -3376,6 +3520,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
3376
3520
  ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
3377
3521
  {
3378
3522
  DEBUGLOG(4, "ZSTD_initCStream_internal");
3523
+ params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
3379
3524
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
3380
3525
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
3381
3526
 
@@ -3442,25 +3587,21 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
3442
3587
  (U32)pledgedSrcSize, params.fParams.contentSizeFlag);
3443
3588
  CHECK_F( ZSTD_checkCParams(params.cParams) );
3444
3589
  if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
3445
- { ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3446
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize);
3447
- }
3590
+ zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3591
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, zcs->requestedParams, pledgedSrcSize);
3448
3592
  }
3449
3593
 
3450
3594
  size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
3451
3595
  {
3452
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
3453
- ZSTD_CCtx_params const cctxParams =
3454
- ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3455
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
3596
+ ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
3597
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, zcs->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN);
3456
3598
  }
3457
3599
 
3458
3600
  size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
3459
3601
  {
3460
3602
  U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
3461
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
3462
- ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
3463
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
3603
+ ZSTD_CCtxParams_init(&zcs->requestedParams, compressionLevel);
3604
+ return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, zcs->requestedParams, pledgedSrcSize);
3464
3605
  }
3465
3606
 
3466
3607
  size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
@@ -3701,6 +3842,7 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
3701
3842
  || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
3702
3843
  ZSTD_CCtx_reset(cctx);
3703
3844
  }
3845
+ DEBUGLOG(5, "completed ZSTD_compress_generic delegating to ZSTDMT_compressStream_generic");
3704
3846
  return flushMin;
3705
3847
  } }
3706
3848
  #endif
@@ -3756,6 +3898,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
3756
3898
 
3757
3899
  #define ZSTD_MAX_CLEVEL 22
3758
3900
  int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
3901
+ int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
3759
3902
 
3760
3903
  static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
3761
3904
  { /* "default" - guarantees a monotonically increasing memory budget */