zstd-ruby 1.3.5.0 → 1.3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 */