extzstd 0.3.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/contrib/zstd/CHANGELOG +39 -2
  4. data/contrib/zstd/CONTRIBUTING.md +3 -3
  5. data/contrib/zstd/Makefile +34 -20
  6. data/contrib/zstd/README.md +6 -2
  7. data/contrib/zstd/SECURITY.md +15 -0
  8. data/contrib/zstd/lib/Makefile +40 -28
  9. data/contrib/zstd/lib/README.md +14 -1
  10. data/contrib/zstd/lib/common/allocations.h +1 -1
  11. data/contrib/zstd/lib/common/bitstream.h +49 -29
  12. data/contrib/zstd/lib/common/compiler.h +114 -22
  13. data/contrib/zstd/lib/common/cpu.h +36 -0
  14. data/contrib/zstd/lib/common/debug.c +6 -0
  15. data/contrib/zstd/lib/common/debug.h +20 -11
  16. data/contrib/zstd/lib/common/error_private.h +45 -36
  17. data/contrib/zstd/lib/common/fse.h +3 -2
  18. data/contrib/zstd/lib/common/fse_decompress.c +19 -17
  19. data/contrib/zstd/lib/common/huf.h +14 -1
  20. data/contrib/zstd/lib/common/mem.h +0 -9
  21. data/contrib/zstd/lib/common/pool.c +1 -1
  22. data/contrib/zstd/lib/common/pool.h +1 -1
  23. data/contrib/zstd/lib/common/portability_macros.h +2 -0
  24. data/contrib/zstd/lib/common/threading.c +8 -2
  25. data/contrib/zstd/lib/common/xxhash.c +5 -11
  26. data/contrib/zstd/lib/common/xxhash.h +2341 -1007
  27. data/contrib/zstd/lib/common/zstd_internal.h +5 -5
  28. data/contrib/zstd/lib/compress/fse_compress.c +8 -7
  29. data/contrib/zstd/lib/compress/huf_compress.c +54 -25
  30. data/contrib/zstd/lib/compress/zstd_compress.c +282 -161
  31. data/contrib/zstd/lib/compress/zstd_compress_internal.h +29 -27
  32. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +224 -113
  33. data/contrib/zstd/lib/compress/zstd_cwksp.h +19 -13
  34. data/contrib/zstd/lib/compress/zstd_double_fast.c +17 -5
  35. data/contrib/zstd/lib/compress/zstd_double_fast.h +11 -0
  36. data/contrib/zstd/lib/compress/zstd_fast.c +14 -6
  37. data/contrib/zstd/lib/compress/zstd_lazy.c +129 -87
  38. data/contrib/zstd/lib/compress/zstd_lazy.h +103 -28
  39. data/contrib/zstd/lib/compress/zstd_ldm.c +8 -2
  40. data/contrib/zstd/lib/compress/zstd_opt.c +216 -112
  41. data/contrib/zstd/lib/compress/zstd_opt.h +31 -7
  42. data/contrib/zstd/lib/compress/zstdmt_compress.c +94 -79
  43. data/contrib/zstd/lib/decompress/huf_decompress.c +188 -126
  44. data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +38 -19
  45. data/contrib/zstd/lib/decompress/zstd_decompress.c +84 -32
  46. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +231 -208
  47. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +1 -1
  48. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +2 -0
  49. data/contrib/zstd/lib/dictBuilder/cover.c +16 -12
  50. data/contrib/zstd/lib/dictBuilder/cover.h +2 -8
  51. data/contrib/zstd/lib/dictBuilder/fastcover.c +2 -2
  52. data/contrib/zstd/lib/dictBuilder/zdict.c +12 -6
  53. data/contrib/zstd/lib/legacy/zstd_legacy.h +30 -0
  54. data/contrib/zstd/lib/legacy/zstd_v01.c +2 -0
  55. data/contrib/zstd/lib/legacy/zstd_v02.c +4 -16
  56. data/contrib/zstd/lib/legacy/zstd_v03.c +4 -16
  57. data/contrib/zstd/lib/legacy/zstd_v04.c +4 -11
  58. data/contrib/zstd/lib/legacy/zstd_v05.c +1 -0
  59. data/contrib/zstd/lib/legacy/zstd_v06.c +2 -9
  60. data/contrib/zstd/lib/legacy/zstd_v07.c +2 -10
  61. data/contrib/zstd/lib/libzstd.mk +34 -11
  62. data/contrib/zstd/lib/zstd.h +129 -60
  63. data/ext/extconf.rb +19 -1
  64. data/ext/extzstd.c +38 -14
  65. data/ext/extzstd.h +33 -6
  66. data/ext/extzstd_stream.c +74 -31
  67. metadata +4 -5
  68. data/contrib/zstd/appveyor.yml +0 -205
  69. data/ext/depend +0 -2
@@ -178,6 +178,7 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
178
178
 
179
179
  size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
180
180
  {
181
+ DEBUGLOG(3, "ZSTD_freeCCtx (address: %p)", (void*)cctx);
181
182
  if (cctx==NULL) return 0; /* support free on NULL */
182
183
  RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
183
184
  "not compatible with static CCtx");
@@ -649,10 +650,11 @@ static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
649
650
  return 0;
650
651
  }
651
652
 
652
- #define BOUNDCHECK(cParam, val) { \
653
- RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
654
- parameter_outOfBound, "Param out of bounds"); \
655
- }
653
+ #define BOUNDCHECK(cParam, val) \
654
+ do { \
655
+ RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
656
+ parameter_outOfBound, "Param out of bounds"); \
657
+ } while (0)
656
658
 
657
659
 
658
660
  static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
@@ -868,7 +870,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
868
870
  #else
869
871
  FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
870
872
  CCtxParams->nbWorkers = value;
871
- return CCtxParams->nbWorkers;
873
+ return (size_t)(CCtxParams->nbWorkers);
872
874
  #endif
873
875
 
874
876
  case ZSTD_c_jobSize :
@@ -892,7 +894,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
892
894
  #else
893
895
  FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
894
896
  CCtxParams->overlapLog = value;
895
- return CCtxParams->overlapLog;
897
+ return (size_t)CCtxParams->overlapLog;
896
898
  #endif
897
899
 
898
900
  case ZSTD_c_rsyncable :
@@ -902,7 +904,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
902
904
  #else
903
905
  FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
904
906
  CCtxParams->rsyncable = value;
905
- return CCtxParams->rsyncable;
907
+ return (size_t)CCtxParams->rsyncable;
906
908
  #endif
907
909
 
908
910
  case ZSTD_c_enableDedicatedDictSearch :
@@ -939,8 +941,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
939
941
  return CCtxParams->ldmParams.hashRateLog;
940
942
 
941
943
  case ZSTD_c_targetCBlockSize :
942
- if (value!=0) /* 0 ==> default */
944
+ if (value!=0) { /* 0 ==> default */
945
+ value = MAX(value, ZSTD_TARGETCBLOCKSIZE_MIN);
943
946
  BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
947
+ }
944
948
  CCtxParams->targetCBlockSize = (U32)value;
945
949
  return CCtxParams->targetCBlockSize;
946
950
 
@@ -968,7 +972,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
968
972
  case ZSTD_c_validateSequences:
969
973
  BOUNDCHECK(ZSTD_c_validateSequences, value);
970
974
  CCtxParams->validateSequences = value;
971
- return CCtxParams->validateSequences;
975
+ return (size_t)CCtxParams->validateSequences;
972
976
 
973
977
  case ZSTD_c_useBlockSplitter:
974
978
  BOUNDCHECK(ZSTD_c_useBlockSplitter, value);
@@ -983,7 +987,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
983
987
  case ZSTD_c_deterministicRefPrefix:
984
988
  BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value);
985
989
  CCtxParams->deterministicRefPrefix = !!value;
986
- return CCtxParams->deterministicRefPrefix;
990
+ return (size_t)CCtxParams->deterministicRefPrefix;
987
991
 
988
992
  case ZSTD_c_prefetchCDictTables:
989
993
  BOUNDCHECK(ZSTD_c_prefetchCDictTables, value);
@@ -993,7 +997,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
993
997
  case ZSTD_c_enableSeqProducerFallback:
994
998
  BOUNDCHECK(ZSTD_c_enableSeqProducerFallback, value);
995
999
  CCtxParams->enableMatchFinderFallback = value;
996
- return CCtxParams->enableMatchFinderFallback;
1000
+ return (size_t)CCtxParams->enableMatchFinderFallback;
997
1001
 
998
1002
  case ZSTD_c_maxBlockSize:
999
1003
  if (value!=0) /* 0 ==> default */
@@ -1363,7 +1367,6 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
1363
1367
  RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
1364
1368
  "Reset parameters is only possible during init stage.");
1365
1369
  ZSTD_clearAllDicts(cctx);
1366
- ZSTD_memset(&cctx->externalMatchCtx, 0, sizeof(cctx->externalMatchCtx));
1367
1370
  return ZSTD_CCtxParams_reset(&cctx->requestedParams);
1368
1371
  }
1369
1372
  return 0;
@@ -1391,11 +1394,12 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
1391
1394
  static ZSTD_compressionParameters
1392
1395
  ZSTD_clampCParams(ZSTD_compressionParameters cParams)
1393
1396
  {
1394
- # define CLAMP_TYPE(cParam, val, type) { \
1395
- ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
1396
- if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
1397
- else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
1398
- }
1397
+ # define CLAMP_TYPE(cParam, val, type) \
1398
+ do { \
1399
+ ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
1400
+ if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
1401
+ else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
1402
+ } while (0)
1399
1403
  # define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
1400
1404
  CLAMP(ZSTD_c_windowLog, cParams.windowLog);
1401
1405
  CLAMP(ZSTD_c_chainLog, cParams.chainLog);
@@ -1467,6 +1471,48 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
1467
1471
  const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
1468
1472
  assert(ZSTD_checkCParams(cPar)==0);
1469
1473
 
1474
+ /* Cascade the selected strategy down to the next-highest one built into
1475
+ * this binary. */
1476
+ #ifdef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR
1477
+ if (cPar.strategy == ZSTD_btultra2) {
1478
+ cPar.strategy = ZSTD_btultra;
1479
+ }
1480
+ if (cPar.strategy == ZSTD_btultra) {
1481
+ cPar.strategy = ZSTD_btopt;
1482
+ }
1483
+ #endif
1484
+ #ifdef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR
1485
+ if (cPar.strategy == ZSTD_btopt) {
1486
+ cPar.strategy = ZSTD_btlazy2;
1487
+ }
1488
+ #endif
1489
+ #ifdef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR
1490
+ if (cPar.strategy == ZSTD_btlazy2) {
1491
+ cPar.strategy = ZSTD_lazy2;
1492
+ }
1493
+ #endif
1494
+ #ifdef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR
1495
+ if (cPar.strategy == ZSTD_lazy2) {
1496
+ cPar.strategy = ZSTD_lazy;
1497
+ }
1498
+ #endif
1499
+ #ifdef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR
1500
+ if (cPar.strategy == ZSTD_lazy) {
1501
+ cPar.strategy = ZSTD_greedy;
1502
+ }
1503
+ #endif
1504
+ #ifdef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR
1505
+ if (cPar.strategy == ZSTD_greedy) {
1506
+ cPar.strategy = ZSTD_dfast;
1507
+ }
1508
+ #endif
1509
+ #ifdef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
1510
+ if (cPar.strategy == ZSTD_dfast) {
1511
+ cPar.strategy = ZSTD_fast;
1512
+ cPar.targetLength = 0;
1513
+ }
1514
+ #endif
1515
+
1470
1516
  switch (mode) {
1471
1517
  case ZSTD_cpm_unknown:
1472
1518
  case ZSTD_cpm_noAttachDict:
@@ -1617,8 +1663,8 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
1617
1663
  + ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32))
1618
1664
  + ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32))
1619
1665
  + ZSTD_cwksp_aligned_alloc_size((1<<Litbits) * sizeof(U32))
1620
- + ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
1621
- + ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
1666
+ + ZSTD_cwksp_aligned_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_match_t))
1667
+ + ZSTD_cwksp_aligned_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));
1622
1668
  size_t const lazyAdditionalSpace = ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)
1623
1669
  ? ZSTD_cwksp_aligned_alloc_size(hSize)
1624
1670
  : 0;
@@ -1707,7 +1753,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1707
1753
  * be needed. However, we still allocate two 0-sized buffers, which can
1708
1754
  * take space under ASAN. */
1709
1755
  return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
1710
- &cParams, &params->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, params->useSequenceProducer, params->maxBlockSize);
1756
+ &cParams, &params->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
1711
1757
  }
1712
1758
 
1713
1759
  size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
@@ -1768,7 +1814,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
1768
1814
 
1769
1815
  return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
1770
1816
  &cParams, &params->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
1771
- ZSTD_CONTENTSIZE_UNKNOWN, params->useSequenceProducer, params->maxBlockSize);
1817
+ ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
1772
1818
  }
1773
1819
  }
1774
1820
 
@@ -2001,8 +2047,8 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
2001
2047
  ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned));
2002
2048
  ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned));
2003
2049
  ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned));
2004
- ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t));
2005
- ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
2050
+ ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t));
2051
+ ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));
2006
2052
  }
2007
2053
 
2008
2054
  ms->cParams = *cParams;
@@ -2074,7 +2120,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
2074
2120
 
2075
2121
  { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));
2076
2122
  size_t const blockSize = MIN(params->maxBlockSize, windowSize);
2077
- size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, params->useSequenceProducer);
2123
+ size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params));
2078
2124
  size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)
2079
2125
  ? ZSTD_compressBound(blockSize) + 1
2080
2126
  : 0;
@@ -2091,8 +2137,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
2091
2137
  size_t const neededSpace =
2092
2138
  ZSTD_estimateCCtxSize_usingCCtxParams_internal(
2093
2139
  &params->cParams, &params->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,
2094
- buffInSize, buffOutSize, pledgedSrcSize, params->useSequenceProducer, params->maxBlockSize);
2095
- int resizeWorkspace;
2140
+ buffInSize, buffOutSize, pledgedSrcSize, ZSTD_hasExtSeqProd(params), params->maxBlockSize);
2096
2141
 
2097
2142
  FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
2098
2143
 
@@ -2101,7 +2146,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
2101
2146
  { /* Check if workspace is large enough, alloc a new one if needed */
2102
2147
  int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
2103
2148
  int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
2104
- resizeWorkspace = workspaceTooSmall || workspaceWasteful;
2149
+ int resizeWorkspace = workspaceTooSmall || workspaceWasteful;
2105
2150
  DEBUGLOG(4, "Need %zu B workspace", neededSpace);
2106
2151
  DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
2107
2152
 
@@ -2176,10 +2221,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
2176
2221
  }
2177
2222
 
2178
2223
  /* reserve space for block-level external sequences */
2179
- if (params->useSequenceProducer) {
2224
+ if (ZSTD_hasExtSeqProd(params)) {
2180
2225
  size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);
2181
- zc->externalMatchCtx.seqBufferCapacity = maxNbExternalSeq;
2182
- zc->externalMatchCtx.seqBuffer =
2226
+ zc->extSeqBufCapacity = maxNbExternalSeq;
2227
+ zc->extSeqBuf =
2183
2228
  (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence));
2184
2229
  }
2185
2230
 
@@ -2564,7 +2609,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
2564
2609
  assert(size < (1U<<31)); /* can be casted to int */
2565
2610
 
2566
2611
  #if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
2567
- /* To validate that the table re-use logic is sound, and that we don't
2612
+ /* To validate that the table reuse logic is sound, and that we don't
2568
2613
  * access table space that we haven't cleaned, we re-"poison" the table
2569
2614
  * space every time we mark it dirty.
2570
2615
  *
@@ -2992,40 +3037,43 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramS
2992
3037
  static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
2993
3038
  { ZSTD_compressBlock_fast /* default for 0 */,
2994
3039
  ZSTD_compressBlock_fast,
2995
- ZSTD_compressBlock_doubleFast,
2996
- ZSTD_compressBlock_greedy,
2997
- ZSTD_compressBlock_lazy,
2998
- ZSTD_compressBlock_lazy2,
2999
- ZSTD_compressBlock_btlazy2,
3000
- ZSTD_compressBlock_btopt,
3001
- ZSTD_compressBlock_btultra,
3002
- ZSTD_compressBlock_btultra2 },
3040
+ ZSTD_COMPRESSBLOCK_DOUBLEFAST,
3041
+ ZSTD_COMPRESSBLOCK_GREEDY,
3042
+ ZSTD_COMPRESSBLOCK_LAZY,
3043
+ ZSTD_COMPRESSBLOCK_LAZY2,
3044
+ ZSTD_COMPRESSBLOCK_BTLAZY2,
3045
+ ZSTD_COMPRESSBLOCK_BTOPT,
3046
+ ZSTD_COMPRESSBLOCK_BTULTRA,
3047
+ ZSTD_COMPRESSBLOCK_BTULTRA2
3048
+ },
3003
3049
  { ZSTD_compressBlock_fast_extDict /* default for 0 */,
3004
3050
  ZSTD_compressBlock_fast_extDict,
3005
- ZSTD_compressBlock_doubleFast_extDict,
3006
- ZSTD_compressBlock_greedy_extDict,
3007
- ZSTD_compressBlock_lazy_extDict,
3008
- ZSTD_compressBlock_lazy2_extDict,
3009
- ZSTD_compressBlock_btlazy2_extDict,
3010
- ZSTD_compressBlock_btopt_extDict,
3011
- ZSTD_compressBlock_btultra_extDict,
3012
- ZSTD_compressBlock_btultra_extDict },
3051
+ ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT,
3052
+ ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT,
3053
+ ZSTD_COMPRESSBLOCK_LAZY_EXTDICT,
3054
+ ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT,
3055
+ ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT,
3056
+ ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT,
3057
+ ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT,
3058
+ ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT
3059
+ },
3013
3060
  { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */,
3014
3061
  ZSTD_compressBlock_fast_dictMatchState,
3015
- ZSTD_compressBlock_doubleFast_dictMatchState,
3016
- ZSTD_compressBlock_greedy_dictMatchState,
3017
- ZSTD_compressBlock_lazy_dictMatchState,
3018
- ZSTD_compressBlock_lazy2_dictMatchState,
3019
- ZSTD_compressBlock_btlazy2_dictMatchState,
3020
- ZSTD_compressBlock_btopt_dictMatchState,
3021
- ZSTD_compressBlock_btultra_dictMatchState,
3022
- ZSTD_compressBlock_btultra_dictMatchState },
3062
+ ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE,
3063
+ ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE,
3064
+ ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE,
3065
+ ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE,
3066
+ ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE,
3067
+ ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE,
3068
+ ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE,
3069
+ ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE
3070
+ },
3023
3071
  { NULL /* default for 0 */,
3024
3072
  NULL,
3025
3073
  NULL,
3026
- ZSTD_compressBlock_greedy_dedicatedDictSearch,
3027
- ZSTD_compressBlock_lazy_dedicatedDictSearch,
3028
- ZSTD_compressBlock_lazy2_dedicatedDictSearch,
3074
+ ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH,
3075
+ ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH,
3076
+ ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH,
3029
3077
  NULL,
3030
3078
  NULL,
3031
3079
  NULL,
@@ -3038,18 +3086,26 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramS
3038
3086
  DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder);
3039
3087
  if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) {
3040
3088
  static const ZSTD_blockCompressor rowBasedBlockCompressors[4][3] = {
3041
- { ZSTD_compressBlock_greedy_row,
3042
- ZSTD_compressBlock_lazy_row,
3043
- ZSTD_compressBlock_lazy2_row },
3044
- { ZSTD_compressBlock_greedy_extDict_row,
3045
- ZSTD_compressBlock_lazy_extDict_row,
3046
- ZSTD_compressBlock_lazy2_extDict_row },
3047
- { ZSTD_compressBlock_greedy_dictMatchState_row,
3048
- ZSTD_compressBlock_lazy_dictMatchState_row,
3049
- ZSTD_compressBlock_lazy2_dictMatchState_row },
3050
- { ZSTD_compressBlock_greedy_dedicatedDictSearch_row,
3051
- ZSTD_compressBlock_lazy_dedicatedDictSearch_row,
3052
- ZSTD_compressBlock_lazy2_dedicatedDictSearch_row }
3089
+ {
3090
+ ZSTD_COMPRESSBLOCK_GREEDY_ROW,
3091
+ ZSTD_COMPRESSBLOCK_LAZY_ROW,
3092
+ ZSTD_COMPRESSBLOCK_LAZY2_ROW
3093
+ },
3094
+ {
3095
+ ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW,
3096
+ ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW,
3097
+ ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW
3098
+ },
3099
+ {
3100
+ ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW,
3101
+ ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW,
3102
+ ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW
3103
+ },
3104
+ {
3105
+ ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW,
3106
+ ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW,
3107
+ ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW
3108
+ }
3053
3109
  };
3054
3110
  DEBUGLOG(4, "Selecting a row-based matchfinder");
3055
3111
  assert(useRowMatchFinder != ZSTD_ps_auto);
@@ -3192,7 +3248,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3192
3248
  /* External matchfinder + LDM is technically possible, just not implemented yet.
3193
3249
  * We need to revisit soon and implement it. */
3194
3250
  RETURN_ERROR_IF(
3195
- zc->appliedParams.useSequenceProducer,
3251
+ ZSTD_hasExtSeqProd(&zc->appliedParams),
3196
3252
  parameter_combination_unsupported,
3197
3253
  "Long-distance matching with external sequence producer enabled is not currently supported."
3198
3254
  );
@@ -3211,7 +3267,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3211
3267
  /* External matchfinder + LDM is technically possible, just not implemented yet.
3212
3268
  * We need to revisit soon and implement it. */
3213
3269
  RETURN_ERROR_IF(
3214
- zc->appliedParams.useSequenceProducer,
3270
+ ZSTD_hasExtSeqProd(&zc->appliedParams),
3215
3271
  parameter_combination_unsupported,
3216
3272
  "Long-distance matching with external sequence producer enabled is not currently supported."
3217
3273
  );
@@ -3230,18 +3286,18 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3230
3286
  zc->appliedParams.useRowMatchFinder,
3231
3287
  src, srcSize);
3232
3288
  assert(ldmSeqStore.pos == ldmSeqStore.size);
3233
- } else if (zc->appliedParams.useSequenceProducer) {
3289
+ } else if (ZSTD_hasExtSeqProd(&zc->appliedParams)) {
3234
3290
  assert(
3235
- zc->externalMatchCtx.seqBufferCapacity >= ZSTD_sequenceBound(srcSize)
3291
+ zc->extSeqBufCapacity >= ZSTD_sequenceBound(srcSize)
3236
3292
  );
3237
- assert(zc->externalMatchCtx.mFinder != NULL);
3293
+ assert(zc->appliedParams.extSeqProdFunc != NULL);
3238
3294
 
3239
3295
  { U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog;
3240
3296
 
3241
- size_t const nbExternalSeqs = (zc->externalMatchCtx.mFinder)(
3242
- zc->externalMatchCtx.mState,
3243
- zc->externalMatchCtx.seqBuffer,
3244
- zc->externalMatchCtx.seqBufferCapacity,
3297
+ size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)(
3298
+ zc->appliedParams.extSeqProdState,
3299
+ zc->extSeqBuf,
3300
+ zc->extSeqBufCapacity,
3245
3301
  src, srcSize,
3246
3302
  NULL, 0, /* dict and dictSize, currently not supported */
3247
3303
  zc->appliedParams.compressionLevel,
@@ -3249,21 +3305,21 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3249
3305
  );
3250
3306
 
3251
3307
  size_t const nbPostProcessedSeqs = ZSTD_postProcessSequenceProducerResult(
3252
- zc->externalMatchCtx.seqBuffer,
3308
+ zc->extSeqBuf,
3253
3309
  nbExternalSeqs,
3254
- zc->externalMatchCtx.seqBufferCapacity,
3310
+ zc->extSeqBufCapacity,
3255
3311
  srcSize
3256
3312
  );
3257
3313
 
3258
3314
  /* Return early if there is no error, since we don't need to worry about last literals */
3259
3315
  if (!ZSTD_isError(nbPostProcessedSeqs)) {
3260
3316
  ZSTD_sequencePosition seqPos = {0,0,0};
3261
- size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->externalMatchCtx.seqBuffer, nbPostProcessedSeqs);
3317
+ size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs);
3262
3318
  RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, "External sequences imply too large a block!");
3263
3319
  FORWARD_IF_ERROR(
3264
3320
  ZSTD_copySequencesToSeqStoreExplicitBlockDelim(
3265
3321
  zc, &seqPos,
3266
- zc->externalMatchCtx.seqBuffer, nbPostProcessedSeqs,
3322
+ zc->extSeqBuf, nbPostProcessedSeqs,
3267
3323
  src, srcSize,
3268
3324
  zc->appliedParams.searchForExternalRepcodes
3269
3325
  ),
@@ -3280,9 +3336,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3280
3336
  }
3281
3337
 
3282
3338
  /* Fallback to software matchfinder */
3283
- { ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy,
3284
- zc->appliedParams.useRowMatchFinder,
3285
- dictMode);
3339
+ { ZSTD_blockCompressor const blockCompressor =
3340
+ ZSTD_selectBlockCompressor(
3341
+ zc->appliedParams.cParams.strategy,
3342
+ zc->appliedParams.useRowMatchFinder,
3343
+ dictMode);
3286
3344
  ms->ldmSeqStore = NULL;
3287
3345
  DEBUGLOG(
3288
3346
  5,
@@ -3292,9 +3350,10 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3292
3350
  lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
3293
3351
  } }
3294
3352
  } else { /* not long range mode and no external matchfinder */
3295
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy,
3296
- zc->appliedParams.useRowMatchFinder,
3297
- dictMode);
3353
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(
3354
+ zc->appliedParams.cParams.strategy,
3355
+ zc->appliedParams.useRowMatchFinder,
3356
+ dictMode);
3298
3357
  ms->ldmSeqStore = NULL;
3299
3358
  lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
3300
3359
  }
@@ -3304,29 +3363,38 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
3304
3363
  return ZSTDbss_compress;
3305
3364
  }
3306
3365
 
3307
- static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
3366
+ static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const seqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM])
3308
3367
  {
3309
- const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
3310
- const seqDef* seqStoreSeqs = seqStore->sequencesStart;
3311
- size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs;
3312
- size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart);
3313
- size_t literalsRead = 0;
3314
- size_t lastLLSize;
3368
+ const seqDef* inSeqs = seqStore->sequencesStart;
3369
+ const size_t nbInSequences = seqStore->sequences - inSeqs;
3370
+ const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart);
3315
3371
 
3316
- ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
3372
+ ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex;
3373
+ const size_t nbOutSequences = nbInSequences + 1;
3374
+ size_t nbOutLiterals = 0;
3375
+ repcodes_t repcodes;
3317
3376
  size_t i;
3318
- repcodes_t updatedRepcodes;
3319
3377
 
3320
- assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
3321
- /* Ensure we have enough space for last literals "sequence" */
3322
- assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
3323
- ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
3324
- for (i = 0; i < seqStoreSeqSize; ++i) {
3325
- U32 rawOffset = seqStoreSeqs[i].offBase - ZSTD_REP_NUM;
3326
- outSeqs[i].litLength = seqStoreSeqs[i].litLength;
3327
- outSeqs[i].matchLength = seqStoreSeqs[i].mlBase + MINMATCH;
3378
+ /* Bounds check that we have enough space for every input sequence
3379
+ * and the block delimiter
3380
+ */
3381
+ assert(seqCollector->seqIndex <= seqCollector->maxSequences);
3382
+ RETURN_ERROR_IF(
3383
+ nbOutSequences > (size_t)(seqCollector->maxSequences - seqCollector->seqIndex),
3384
+ dstSize_tooSmall,
3385
+ "Not enough space to copy sequences");
3386
+
3387
+ ZSTD_memcpy(&repcodes, prevRepcodes, sizeof(repcodes));
3388
+ for (i = 0; i < nbInSequences; ++i) {
3389
+ U32 rawOffset;
3390
+ outSeqs[i].litLength = inSeqs[i].litLength;
3391
+ outSeqs[i].matchLength = inSeqs[i].mlBase + MINMATCH;
3328
3392
  outSeqs[i].rep = 0;
3329
3393
 
3394
+ /* Handle the possible single length >= 64K
3395
+ * There can only be one because we add MINMATCH to every match length,
3396
+ * and blocks are at most 128K.
3397
+ */
3330
3398
  if (i == seqStore->longLengthPos) {
3331
3399
  if (seqStore->longLengthType == ZSTD_llt_literalLength) {
3332
3400
  outSeqs[i].litLength += 0x10000;
@@ -3335,41 +3403,55 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
3335
3403
  }
3336
3404
  }
3337
3405
 
3338
- if (seqStoreSeqs[i].offBase <= ZSTD_REP_NUM) {
3339
- /* Derive the correct offset corresponding to a repcode */
3340
- outSeqs[i].rep = seqStoreSeqs[i].offBase;
3406
+ /* Determine the raw offset given the offBase, which may be a repcode. */
3407
+ if (OFFBASE_IS_REPCODE(inSeqs[i].offBase)) {
3408
+ const U32 repcode = OFFBASE_TO_REPCODE(inSeqs[i].offBase);
3409
+ assert(repcode > 0);
3410
+ outSeqs[i].rep = repcode;
3341
3411
  if (outSeqs[i].litLength != 0) {
3342
- rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
3412
+ rawOffset = repcodes.rep[repcode - 1];
3343
3413
  } else {
3344
- if (outSeqs[i].rep == 3) {
3345
- rawOffset = updatedRepcodes.rep[0] - 1;
3414
+ if (repcode == 3) {
3415
+ assert(repcodes.rep[0] > 1);
3416
+ rawOffset = repcodes.rep[0] - 1;
3346
3417
  } else {
3347
- rawOffset = updatedRepcodes.rep[outSeqs[i].rep];
3418
+ rawOffset = repcodes.rep[repcode];
3348
3419
  }
3349
3420
  }
3421
+ } else {
3422
+ rawOffset = OFFBASE_TO_OFFSET(inSeqs[i].offBase);
3350
3423
  }
3351
3424
  outSeqs[i].offset = rawOffset;
3352
- /* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
3353
- so we provide seqStoreSeqs[i].offset - 1 */
3354
- ZSTD_updateRep(updatedRepcodes.rep,
3355
- seqStoreSeqs[i].offBase,
3356
- seqStoreSeqs[i].litLength == 0);
3357
- literalsRead += outSeqs[i].litLength;
3425
+
3426
+ /* Update repcode history for the sequence */
3427
+ ZSTD_updateRep(repcodes.rep,
3428
+ inSeqs[i].offBase,
3429
+ inSeqs[i].litLength == 0);
3430
+
3431
+ nbOutLiterals += outSeqs[i].litLength;
3358
3432
  }
3359
3433
  /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
3360
3434
  * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker
3361
3435
  * for the block boundary, according to the API.
3362
3436
  */
3363
- assert(seqStoreLiteralsSize >= literalsRead);
3364
- lastLLSize = seqStoreLiteralsSize - literalsRead;
3365
- outSeqs[i].litLength = (U32)lastLLSize;
3366
- outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0;
3367
- seqStoreSeqSize++;
3368
- zc->seqCollector.seqIndex += seqStoreSeqSize;
3437
+ assert(nbInLiterals >= nbOutLiterals);
3438
+ {
3439
+ const size_t lastLLSize = nbInLiterals - nbOutLiterals;
3440
+ outSeqs[nbInSequences].litLength = (U32)lastLLSize;
3441
+ outSeqs[nbInSequences].matchLength = 0;
3442
+ outSeqs[nbInSequences].offset = 0;
3443
+ assert(nbOutSequences == nbInSequences + 1);
3444
+ }
3445
+ seqCollector->seqIndex += nbOutSequences;
3446
+ assert(seqCollector->seqIndex <= seqCollector->maxSequences);
3447
+
3448
+ return 0;
3369
3449
  }
3370
3450
 
3371
3451
  size_t ZSTD_sequenceBound(size_t srcSize) {
3372
- return (srcSize / ZSTD_MINMATCH_MIN) + 1;
3452
+ const size_t maxNbSeq = (srcSize / ZSTD_MINMATCH_MIN) + 1;
3453
+ const size_t maxNbDelims = (srcSize / ZSTD_BLOCKSIZE_MAX_MIN) + 1;
3454
+ return maxNbSeq + maxNbDelims;
3373
3455
  }
3374
3456
 
3375
3457
  size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
@@ -3378,6 +3460,16 @@ size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
3378
3460
  const size_t dstCapacity = ZSTD_compressBound(srcSize);
3379
3461
  void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
3380
3462
  SeqCollector seqCollector;
3463
+ {
3464
+ int targetCBlockSize;
3465
+ FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), "");
3466
+ RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, "targetCBlockSize != 0");
3467
+ }
3468
+ {
3469
+ int nbWorkers;
3470
+ FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), "");
3471
+ RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, "nbWorkers != 0");
3472
+ }
3381
3473
 
3382
3474
  RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
3383
3475
 
@@ -3387,8 +3479,12 @@ size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
3387
3479
  seqCollector.maxSequences = outSeqsSize;
3388
3480
  zc->seqCollector = seqCollector;
3389
3481
 
3390
- ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
3391
- ZSTD_customFree(dst, ZSTD_defaultCMem);
3482
+ {
3483
+ const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
3484
+ ZSTD_customFree(dst, ZSTD_defaultCMem);
3485
+ FORWARD_IF_ERROR(ret, "ZSTD_compress2 failed");
3486
+ }
3487
+ assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize));
3392
3488
  return zc->seqCollector.seqIndex;
3393
3489
  }
3394
3490
 
@@ -3981,8 +4077,9 @@ ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc,
3981
4077
  cSeqsSize = 1;
3982
4078
  }
3983
4079
 
4080
+ /* Sequence collection not supported when block splitting */
3984
4081
  if (zc->seqCollector.collectSequences) {
3985
- ZSTD_copyBlockSequences(zc);
4082
+ FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, seqStore, dRepOriginal.rep), "copyBlockSequences failed");
3986
4083
  ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
3987
4084
  return 0;
3988
4085
  }
@@ -4204,6 +4301,7 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
4204
4301
  if (bss == ZSTDbss_noCompress) {
4205
4302
  if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
4206
4303
  zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
4304
+ RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block");
4207
4305
  cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
4208
4306
  FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
4209
4307
  DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block");
@@ -4236,11 +4334,15 @@ ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
4236
4334
 
4237
4335
  { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
4238
4336
  FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
4239
- if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
4337
+ if (bss == ZSTDbss_noCompress) {
4338
+ RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block");
4339
+ cSize = 0;
4340
+ goto out;
4341
+ }
4240
4342
  }
4241
4343
 
4242
4344
  if (zc->seqCollector.collectSequences) {
4243
- ZSTD_copyBlockSequences(zc);
4345
+ FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, ZSTD_getSeqStore(zc), zc->blockState.prevCBlock->rep), "copyBlockSequences failed");
4244
4346
  ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
4245
4347
  return 0;
4246
4348
  }
@@ -4553,19 +4655,15 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
4553
4655
  }
4554
4656
  }
4555
4657
 
4556
- size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
4658
+ void ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
4557
4659
  {
4558
- RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
4559
- "wrong cctx stage");
4560
- RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable,
4561
- parameter_unsupported,
4562
- "incompatible with ldm");
4660
+ assert(cctx->stage == ZSTDcs_init);
4661
+ assert(nbSeq == 0 || cctx->appliedParams.ldmParams.enableLdm != ZSTD_ps_enable);
4563
4662
  cctx->externSeqStore.seq = seq;
4564
4663
  cctx->externSeqStore.size = nbSeq;
4565
4664
  cctx->externSeqStore.capacity = nbSeq;
4566
4665
  cctx->externSeqStore.pos = 0;
4567
4666
  cctx->externSeqStore.posInSequence = 0;
4568
- return 0;
4569
4667
  }
4570
4668
 
4571
4669
 
@@ -4760,12 +4858,19 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
4760
4858
  ZSTD_fillHashTable(ms, iend, dtlm, tfp);
4761
4859
  break;
4762
4860
  case ZSTD_dfast:
4861
+ #ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
4763
4862
  ZSTD_fillDoubleHashTable(ms, iend, dtlm, tfp);
4863
+ #else
4864
+ assert(0); /* shouldn't be called: cparams should've been adjusted. */
4865
+ #endif
4764
4866
  break;
4765
4867
 
4766
4868
  case ZSTD_greedy:
4767
4869
  case ZSTD_lazy:
4768
4870
  case ZSTD_lazy2:
4871
+ #if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \
4872
+ || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \
4873
+ || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR)
4769
4874
  assert(srcSize >= HASH_READ_SIZE);
4770
4875
  if (ms->dedicatedDictSearch) {
4771
4876
  assert(ms->chainTable != NULL);
@@ -4782,14 +4887,23 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
4782
4887
  DEBUGLOG(4, "Using chain-based hash table for lazy dict");
4783
4888
  }
4784
4889
  }
4890
+ #else
4891
+ assert(0); /* shouldn't be called: cparams should've been adjusted. */
4892
+ #endif
4785
4893
  break;
4786
4894
 
4787
4895
  case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
4788
4896
  case ZSTD_btopt:
4789
4897
  case ZSTD_btultra:
4790
4898
  case ZSTD_btultra2:
4899
+ #if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \
4900
+ || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \
4901
+ || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)
4791
4902
  assert(srcSize >= HASH_READ_SIZE);
4792
4903
  ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
4904
+ #else
4905
+ assert(0); /* shouldn't be called: cparams should've been adjusted. */
4906
+ #endif
4793
4907
  break;
4794
4908
 
4795
4909
  default:
@@ -4836,11 +4950,10 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
4836
4950
 
4837
4951
  /* We only set the loaded table as valid if it contains all non-zero
4838
4952
  * weights. Otherwise, we set it to check */
4839
- if (!hasZeroWeights)
4953
+ if (!hasZeroWeights && maxSymbolValue == 255)
4840
4954
  bs->entropy.huf.repeatMode = HUF_repeat_valid;
4841
4955
 
4842
4956
  RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
4843
- RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
4844
4957
  dictPtr += hufHeaderSize;
4845
4958
  }
4846
4959
 
@@ -5107,14 +5220,13 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
5107
5220
  {
5108
5221
  BYTE* const ostart = (BYTE*)dst;
5109
5222
  BYTE* op = ostart;
5110
- size_t fhSize = 0;
5111
5223
 
5112
5224
  DEBUGLOG(4, "ZSTD_writeEpilogue");
5113
5225
  RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
5114
5226
 
5115
5227
  /* special case : empty frame */
5116
5228
  if (cctx->stage == ZSTDcs_init) {
5117
- fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
5229
+ size_t fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
5118
5230
  FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
5119
5231
  dstCapacity -= fhSize;
5120
5232
  op += fhSize;
@@ -5124,8 +5236,9 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
5124
5236
  if (cctx->stage != ZSTDcs_ending) {
5125
5237
  /* write one last empty block, make it the "last" block */
5126
5238
  U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
5127
- RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
5128
- MEM_writeLE32(op, cBlockHeader24);
5239
+ ZSTD_STATIC_ASSERT(ZSTD_BLOCKHEADERSIZE == 3);
5240
+ RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, "no room for epilogue");
5241
+ MEM_writeLE24(op, cBlockHeader24);
5129
5242
  op += ZSTD_blockHeaderSize;
5130
5243
  dstCapacity -= ZSTD_blockHeaderSize;
5131
5244
  }
@@ -5455,7 +5568,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2(
5455
5568
  cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch,
5456
5569
  customMem);
5457
5570
 
5458
- if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
5571
+ if (!cdict || ZSTD_isError( ZSTD_initCDict_internal(cdict,
5459
5572
  dict, dictSize,
5460
5573
  dictLoadMethod, dictContentType,
5461
5574
  cctxParams) )) {
@@ -5879,7 +5992,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
5879
5992
  if (zcs->appliedParams.inBufferMode == ZSTD_bm_stable) {
5880
5993
  assert(input->pos >= zcs->stableIn_notConsumed);
5881
5994
  input->pos -= zcs->stableIn_notConsumed;
5882
- ip -= zcs->stableIn_notConsumed;
5995
+ if (ip) ip -= zcs->stableIn_notConsumed;
5883
5996
  zcs->stableIn_notConsumed = 0;
5884
5997
  }
5885
5998
  if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
@@ -6138,7 +6251,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
6138
6251
  #ifdef ZSTD_MULTITHREAD
6139
6252
  /* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */
6140
6253
  RETURN_ERROR_IF(
6141
- params.useSequenceProducer == 1 && params.nbWorkers >= 1,
6254
+ ZSTD_hasExtSeqProd(&params) && params.nbWorkers >= 1,
6142
6255
  parameter_combination_unsupported,
6143
6256
  "External sequence producer isn't supported with nbWorkers >= 1"
6144
6257
  );
@@ -6430,7 +6543,7 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
6430
6543
  if (cctx->appliedParams.validateSequences) {
6431
6544
  seqPos->posInSrc += litLength + matchLength;
6432
6545
  FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
6433
- cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useSequenceProducer),
6546
+ cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)),
6434
6547
  "Sequence validation failed");
6435
6548
  }
6436
6549
  RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,
@@ -6568,7 +6681,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
6568
6681
  if (cctx->appliedParams.validateSequences) {
6569
6682
  seqPos->posInSrc += litLength + matchLength;
6570
6683
  FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
6571
- cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useSequenceProducer),
6684
+ cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)),
6572
6685
  "Sequence validation failed");
6573
6686
  }
6574
6687
  DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength);
@@ -7014,19 +7127,27 @@ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeH
7014
7127
  }
7015
7128
 
7016
7129
  void ZSTD_registerSequenceProducer(
7017
- ZSTD_CCtx* zc, void* mState,
7018
- ZSTD_sequenceProducer_F* mFinder
7130
+ ZSTD_CCtx* zc,
7131
+ void* extSeqProdState,
7132
+ ZSTD_sequenceProducer_F extSeqProdFunc
7133
+ ) {
7134
+ assert(zc != NULL);
7135
+ ZSTD_CCtxParams_registerSequenceProducer(
7136
+ &zc->requestedParams, extSeqProdState, extSeqProdFunc
7137
+ );
7138
+ }
7139
+
7140
+ void ZSTD_CCtxParams_registerSequenceProducer(
7141
+ ZSTD_CCtx_params* params,
7142
+ void* extSeqProdState,
7143
+ ZSTD_sequenceProducer_F extSeqProdFunc
7019
7144
  ) {
7020
- if (mFinder != NULL) {
7021
- ZSTD_externalMatchCtx emctx;
7022
- emctx.mState = mState;
7023
- emctx.mFinder = mFinder;
7024
- emctx.seqBuffer = NULL;
7025
- emctx.seqBufferCapacity = 0;
7026
- zc->externalMatchCtx = emctx;
7027
- zc->requestedParams.useSequenceProducer = 1;
7145
+ assert(params != NULL);
7146
+ if (extSeqProdFunc != NULL) {
7147
+ params->extSeqProdFunc = extSeqProdFunc;
7148
+ params->extSeqProdState = extSeqProdState;
7028
7149
  } else {
7029
- ZSTD_memset(&zc->externalMatchCtx, 0, sizeof(zc->externalMatchCtx));
7030
- zc->requestedParams.useSequenceProducer = 0;
7150
+ params->extSeqProdFunc = NULL;
7151
+ params->extSeqProdState = NULL;
7031
7152
  }
7032
7153
  }