zstd-ruby 1.5.1.1 → 1.5.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +57 -4
  4. data/Rakefile +8 -2
  5. data/ext/zstdruby/{zstdruby.h → common.h} +2 -0
  6. data/ext/zstdruby/libzstd/common/pool.c +11 -6
  7. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  8. data/ext/zstdruby/libzstd/common/portability_macros.h +6 -0
  9. data/ext/zstdruby/libzstd/common/zstd_internal.h +3 -4
  10. data/ext/zstdruby/libzstd/compress/zstd_compress.c +114 -96
  11. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +72 -39
  12. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +10 -10
  13. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +1 -1
  14. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +38 -24
  15. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +10 -10
  16. data/ext/zstdruby/libzstd/compress/zstd_fast.c +11 -11
  17. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +66 -62
  18. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +5 -3
  19. data/ext/zstdruby/libzstd/compress/zstd_opt.c +66 -43
  20. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +17 -9
  21. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +4 -1
  22. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +2 -2
  23. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +17 -3
  24. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +2 -2
  25. data/ext/zstdruby/libzstd/zstd.h +1 -1
  26. data/ext/zstdruby/main.c +14 -0
  27. data/ext/zstdruby/streaming_compress.c +183 -0
  28. data/ext/zstdruby/streaming_compress.h +5 -0
  29. data/ext/zstdruby/streaming_decompress.c +123 -0
  30. data/ext/zstdruby/zstdruby.c +4 -6
  31. data/lib/zstd-ruby/version.rb +1 -1
  32. data/zstd-ruby.gemspec +1 -1
  33. metadata +11 -40
  34. data/.github/dependabot.yml +0 -8
  35. data/.github/workflows/ruby.yml +0 -35
  36. data/ext/zstdruby/libzstd/.gitignore +0 -3
  37. data/ext/zstdruby/libzstd/BUCK +0 -232
  38. data/ext/zstdruby/libzstd/Makefile +0 -357
  39. data/ext/zstdruby/libzstd/README.md +0 -217
  40. data/ext/zstdruby/libzstd/deprecated/zbuff.h +0 -214
  41. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +0 -26
  42. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +0 -167
  43. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +0 -75
  44. data/ext/zstdruby/libzstd/dll/example/Makefile +0 -48
  45. data/ext/zstdruby/libzstd/dll/example/README.md +0 -63
  46. data/ext/zstdruby/libzstd/dll/example/build_package.bat +0 -20
  47. data/ext/zstdruby/libzstd/dll/example/fullbench-dll.sln +0 -25
  48. data/ext/zstdruby/libzstd/dll/example/fullbench-dll.vcxproj +0 -181
  49. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +0 -415
  50. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +0 -2158
  51. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +0 -94
  52. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +0 -3518
  53. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +0 -93
  54. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +0 -3160
  55. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +0 -93
  56. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +0 -3647
  57. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +0 -142
  58. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +0 -4050
  59. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +0 -162
  60. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +0 -4154
  61. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +0 -172
  62. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +0 -4541
  63. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +0 -187
  64. data/ext/zstdruby/libzstd/libzstd.mk +0 -185
  65. data/ext/zstdruby/libzstd/libzstd.pc.in +0 -16
  66. data/ext/zstdruby/libzstd/modulemap/module.modulemap +0 -4
@@ -204,7 +204,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
204
204
  1, 1, 1, 1, 1, 1, 1, 1,
205
205
  1, 1, 1, 1
206
206
  };
207
- ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs)); optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1);
207
+ ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs));
208
+ optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1);
208
209
  }
209
210
 
210
211
  { unsigned ml;
@@ -219,7 +220,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
219
220
  1, 1, 1, 1, 1, 1, 1, 1,
220
221
  1, 1, 1, 1, 1, 1, 1, 1
221
222
  };
222
- ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs)); optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);
223
+ ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs));
224
+ optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);
223
225
  }
224
226
 
225
227
 
@@ -267,7 +269,16 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
267
269
  * cost of literalLength symbol */
268
270
  static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel)
269
271
  {
270
- if (optPtr->priceType == zop_predef) return WEIGHT(litLength, optLevel);
272
+ assert(litLength <= ZSTD_BLOCKSIZE_MAX);
273
+ if (optPtr->priceType == zop_predef)
274
+ return WEIGHT(litLength, optLevel);
275
+ /* We can't compute the litLength price for sizes >= ZSTD_BLOCKSIZE_MAX
276
+ * because it isn't representable in the zstd format. So instead just
277
+ * call it 1 bit more than ZSTD_BLOCKSIZE_MAX - 1. In this case the block
278
+ * would be all literals.
279
+ */
280
+ if (litLength == ZSTD_BLOCKSIZE_MAX)
281
+ return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel);
271
282
 
272
283
  /* dynamic statistics */
273
284
  { U32 const llCode = ZSTD_LLcode(litLength);
@@ -280,15 +291,17 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
280
291
  /* ZSTD_getMatchPrice() :
281
292
  * Provides the cost of the match part (offset + matchLength) of a sequence
282
293
  * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
283
- * optLevel: when <2, favors small offset for decompression speed (improved cache efficiency) */
294
+ * @offcode : expects a scale where 0,1,2 are repcodes 1-3, and 3+ are real_offsets+2
295
+ * @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency)
296
+ */
284
297
  FORCE_INLINE_TEMPLATE U32
285
- ZSTD_getMatchPrice(U32 const offset,
298
+ ZSTD_getMatchPrice(U32 const offcode,
286
299
  U32 const matchLength,
287
300
  const optState_t* const optPtr,
288
301
  int const optLevel)
289
302
  {
290
303
  U32 price;
291
- U32 const offCode = ZSTD_highbit32(offset+1);
304
+ U32 const offCode = ZSTD_highbit32(STORED_TO_OFFBASE(offcode));
292
305
  U32 const mlBase = matchLength - MINMATCH;
293
306
  assert(matchLength >= MINMATCH);
294
307
 
@@ -331,8 +344,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
331
344
  optPtr->litLengthSum++;
332
345
  }
333
346
 
334
- /* match offset code (0-2=>repCode; 3+=>offset+2) */
335
- { U32 const offCode = ZSTD_highbit32(offsetCode+1);
347
+ /* offset code : expected to follow storeSeq() numeric representation */
348
+ { U32 const offCode = ZSTD_highbit32(STORED_TO_OFFBASE(offsetCode));
336
349
  assert(offCode <= MaxOff);
337
350
  optPtr->offCodeFreq[offCode]++;
338
351
  optPtr->offCodeSum++;
@@ -631,7 +644,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
631
644
  DEBUGLOG(8, "found repCode %u (ll0:%u, offset:%u) of length %u",
632
645
  repCode, ll0, repOffset, repLen);
633
646
  bestLength = repLen;
634
- matches[mnum].off = repCode - ll0;
647
+ matches[mnum].off = STORE_REPCODE(repCode - ll0 + 1); /* expect value between 1 and 3 */
635
648
  matches[mnum].len = (U32)repLen;
636
649
  mnum++;
637
650
  if ( (repLen > sufficient_len)
@@ -660,7 +673,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
660
673
  bestLength = mlen;
661
674
  assert(curr > matchIndex3);
662
675
  assert(mnum==0); /* no prior solution */
663
- matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE;
676
+ matches[0].off = STORE_OFFSET(curr - matchIndex3);
664
677
  matches[0].len = (U32)mlen;
665
678
  mnum = 1;
666
679
  if ( (mlen > sufficient_len) |
@@ -694,12 +707,12 @@ U32 ZSTD_insertBtAndGetAllMatches (
694
707
 
695
708
  if (matchLength > bestLength) {
696
709
  DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)",
697
- (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
710
+ (U32)matchLength, curr - matchIndex, STORE_OFFSET(curr - matchIndex));
698
711
  assert(matchEndIdx > matchIndex);
699
712
  if (matchLength > matchEndIdx - matchIndex)
700
713
  matchEndIdx = matchIndex + (U32)matchLength;
701
714
  bestLength = matchLength;
702
- matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
715
+ matches[mnum].off = STORE_OFFSET(curr - matchIndex);
703
716
  matches[mnum].len = (U32)matchLength;
704
717
  mnum++;
705
718
  if ( (matchLength > ZSTD_OPT_NUM)
@@ -742,11 +755,11 @@ U32 ZSTD_insertBtAndGetAllMatches (
742
755
  if (matchLength > bestLength) {
743
756
  matchIndex = dictMatchIndex + dmsIndexDelta;
744
757
  DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)",
745
- (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
758
+ (U32)matchLength, curr - matchIndex, STORE_OFFSET(curr - matchIndex));
746
759
  if (matchLength > matchEndIdx - matchIndex)
747
760
  matchEndIdx = matchIndex + (U32)matchLength;
748
761
  bestLength = matchLength;
749
- matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
762
+ matches[mnum].off = STORE_OFFSET(curr - matchIndex);
750
763
  matches[mnum].len = (U32)matchLength;
751
764
  mnum++;
752
765
  if ( (matchLength > ZSTD_OPT_NUM)
@@ -835,7 +848,8 @@ GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState)
835
848
  ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 6) \
836
849
  }
837
850
 
838
- static ZSTD_getAllMatchesFn ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const* ms, ZSTD_dictMode_e const dictMode)
851
+ static ZSTD_getAllMatchesFn
852
+ ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const* ms, ZSTD_dictMode_e const dictMode)
839
853
  {
840
854
  ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = {
841
855
  ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict),
@@ -854,16 +868,18 @@ static ZSTD_getAllMatchesFn ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const*
854
868
 
855
869
  /* Struct containing info needed to make decision about ldm inclusion */
856
870
  typedef struct {
857
- rawSeqStore_t seqStore; /* External match candidates store for this block */
858
- U32 startPosInBlock; /* Start position of the current match candidate */
859
- U32 endPosInBlock; /* End position of the current match candidate */
860
- U32 offset; /* Offset of the match candidate */
871
+ rawSeqStore_t seqStore; /* External match candidates store for this block */
872
+ U32 startPosInBlock; /* Start position of the current match candidate */
873
+ U32 endPosInBlock; /* End position of the current match candidate */
874
+ U32 offset; /* Offset of the match candidate */
861
875
  } ZSTD_optLdm_t;
862
876
 
863
877
  /* ZSTD_optLdm_skipRawSeqStoreBytes():
864
- * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
878
+ * Moves forward in @rawSeqStore by @nbBytes,
879
+ * which will update the fields 'pos' and 'posInSequence'.
865
880
  */
866
- static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
881
+ static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes)
882
+ {
867
883
  U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
868
884
  while (currPos && rawSeqStore->pos < rawSeqStore->size) {
869
885
  rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
@@ -884,8 +900,10 @@ static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t
884
900
  * Calculates the beginning and end of the next match in the current block.
885
901
  * Updates 'pos' and 'posInSequence' of the ldmSeqStore.
886
902
  */
887
- static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
888
- U32 blockBytesRemaining) {
903
+ static void
904
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
905
+ U32 blockBytesRemaining)
906
+ {
889
907
  rawSeq currSeq;
890
908
  U32 currBlockEndPos;
891
909
  U32 literalsBytesRemaining;
@@ -897,8 +915,8 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
897
915
  optLdm->endPosInBlock = UINT_MAX;
898
916
  return;
899
917
  }
900
- /* Calculate appropriate bytes left in matchLength and litLength after adjusting
901
- based on ldmSeqStore->posInSequence */
918
+ /* Calculate appropriate bytes left in matchLength and litLength
919
+ * after adjusting based on ldmSeqStore->posInSequence */
902
920
  currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];
903
921
  assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);
904
922
  currBlockEndPos = currPosInBlock + blockBytesRemaining;
@@ -934,15 +952,16 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
934
952
  }
935
953
 
936
954
  /* ZSTD_optLdm_maybeAddMatch():
937
- * Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
938
- * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
955
+ * Adds a match if it's long enough,
956
+ * based on it's 'matchStartPosInBlock' and 'matchEndPosInBlock',
957
+ * into 'matches'. Maintains the correct ordering of 'matches'.
939
958
  */
940
959
  static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
941
- ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
942
- U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
960
+ const ZSTD_optLdm_t* optLdm, U32 currPosInBlock)
961
+ {
962
+ U32 const posDiff = currPosInBlock - optLdm->startPosInBlock;
943
963
  /* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
944
- U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
945
- U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE;
964
+ U32 const candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
946
965
 
947
966
  /* Ensure that current block position is not outside of the match */
948
967
  if (currPosInBlock < optLdm->startPosInBlock
@@ -952,6 +971,7 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
952
971
  }
953
972
 
954
973
  if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {
974
+ U32 const candidateOffCode = STORE_OFFSET(optLdm->offset);
955
975
  DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
956
976
  candidateOffCode, candidateMatchLength, currPosInBlock);
957
977
  matches[*nbMatches].len = candidateMatchLength;
@@ -963,8 +983,11 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
963
983
  /* ZSTD_optLdm_processMatchCandidate():
964
984
  * Wrapper function to update ldm seq store and call ldm functions as necessary.
965
985
  */
966
- static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
967
- U32 currPosInBlock, U32 remainingBytes) {
986
+ static void
987
+ ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm,
988
+ ZSTD_match_t* matches, U32* nbMatches,
989
+ U32 currPosInBlock, U32 remainingBytes)
990
+ {
968
991
  if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
969
992
  return;
970
993
  }
@@ -975,7 +998,7 @@ static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_
975
998
  * at the end of a match from the ldm seq store, and will often be some bytes
976
999
  * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
977
1000
  */
978
- U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
1001
+ U32 const posOvershoot = currPosInBlock - optLdm->endPosInBlock;
979
1002
  ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);
980
1003
  }
981
1004
  ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
@@ -1075,14 +1098,14 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1075
1098
 
1076
1099
  /* large match -> immediate encoding */
1077
1100
  { U32 const maxML = matches[nbMatches-1].len;
1078
- U32 const maxOffset = matches[nbMatches-1].off;
1101
+ U32 const maxOffcode = matches[nbMatches-1].off;
1079
1102
  DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
1080
- nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
1103
+ nbMatches, maxML, maxOffcode, (U32)(ip-prefixStart));
1081
1104
 
1082
1105
  if (maxML > sufficient_len) {
1083
1106
  lastSequence.litlen = litlen;
1084
1107
  lastSequence.mlen = maxML;
1085
- lastSequence.off = maxOffset;
1108
+ lastSequence.off = maxOffcode;
1086
1109
  DEBUGLOG(6, "large match (%u>%u), immediate encoding",
1087
1110
  maxML, sufficient_len);
1088
1111
  cur = 0;
@@ -1099,15 +1122,15 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1099
1122
  opt[pos].price = ZSTD_MAX_PRICE; /* mlen, litlen and price will be fixed during forward scanning */
1100
1123
  }
1101
1124
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
1102
- U32 const offset = matches[matchNb].off;
1125
+ U32 const offcode = matches[matchNb].off;
1103
1126
  U32 const end = matches[matchNb].len;
1104
1127
  for ( ; pos <= end ; pos++ ) {
1105
- U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
1128
+ U32 const matchPrice = ZSTD_getMatchPrice(offcode, pos, optStatePtr, optLevel);
1106
1129
  U32 const sequencePrice = literalsPrice + matchPrice;
1107
1130
  DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
1108
1131
  pos, ZSTD_fCost(sequencePrice));
1109
1132
  opt[pos].mlen = pos;
1110
- opt[pos].off = offset;
1133
+ opt[pos].off = offcode;
1111
1134
  opt[pos].litlen = litlen;
1112
1135
  opt[pos].price = (int)sequencePrice;
1113
1136
  } }
@@ -1152,7 +1175,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1152
1175
  assert(cur >= opt[cur].mlen);
1153
1176
  if (opt[cur].mlen != 0) {
1154
1177
  U32 const prev = cur - opt[cur].mlen;
1155
- repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
1178
+ repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
1156
1179
  ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
1157
1180
  } else {
1158
1181
  ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
@@ -1242,7 +1265,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1242
1265
  * update them while traversing the sequences.
1243
1266
  */
1244
1267
  if (lastSequence.mlen != 0) {
1245
- repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
1268
+ repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
1246
1269
  ZSTD_memcpy(rep, &reps, sizeof(reps));
1247
1270
  } else {
1248
1271
  ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
@@ -1286,7 +1309,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1286
1309
 
1287
1310
  assert(anchor + llen <= iend);
1288
1311
  ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
1289
- ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
1312
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen);
1290
1313
  anchor += advance;
1291
1314
  ip = anchor;
1292
1315
  } }
@@ -102,9 +102,8 @@ typedef struct ZSTDMT_bufferPool_s {
102
102
  buffer_t bTable[1]; /* variable size */
103
103
  } ZSTDMT_bufferPool;
104
104
 
105
- static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem)
105
+ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem)
106
106
  {
107
- unsigned const maxNbBuffers = 2*nbWorkers + 3;
108
107
  ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
109
108
  sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
110
109
  if (bufPool==NULL) return NULL;
@@ -160,9 +159,8 @@ static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const
160
159
  }
161
160
 
162
161
 
163
- static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, U32 nbWorkers)
162
+ static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, unsigned maxNbBuffers)
164
163
  {
165
- unsigned const maxNbBuffers = 2*nbWorkers + 3;
166
164
  if (srcBufPool==NULL) return NULL;
167
165
  if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */
168
166
  return srcBufPool;
@@ -171,7 +169,7 @@ static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool,
171
169
  size_t const bSize = srcBufPool->bufferSize; /* forward parameters */
172
170
  ZSTDMT_bufferPool* newBufPool;
173
171
  ZSTDMT_freeBufferPool(srcBufPool);
174
- newBufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
172
+ newBufPool = ZSTDMT_createBufferPool(maxNbBuffers, cMem);
175
173
  if (newBufPool==NULL) return newBufPool;
176
174
  ZSTDMT_setBufferSize(newBufPool, bSize);
177
175
  return newBufPool;
@@ -263,6 +261,16 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
263
261
  ZSTD_customFree(buf.start, bufPool->cMem);
264
262
  }
265
263
 
264
+ /* We need 2 output buffers per worker since each dstBuff must be flushed after it is released.
265
+ * The 3 additional buffers are as follows:
266
+ * 1 buffer for input loading
267
+ * 1 buffer for "next input" when submitting current one
268
+ * 1 buffer stuck in queue */
269
+ #define BUF_POOL_MAX_NB_BUFFERS(nbWorkers) 2*nbWorkers + 3
270
+
271
+ /* After a worker releases its rawSeqStore, it is immediately ready for reuse.
272
+ * So we only need one seq buffer per worker. */
273
+ #define SEQ_POOL_MAX_NB_BUFFERS(nbWorkers) nbWorkers
266
274
 
267
275
  /* ===== Seq Pool Wrapper ====== */
268
276
 
@@ -316,7 +324,7 @@ static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)
316
324
 
317
325
  static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)
318
326
  {
319
- ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
327
+ ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(SEQ_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);
320
328
  if (seqPool == NULL) return NULL;
321
329
  ZSTDMT_setNbSeq(seqPool, 0);
322
330
  return seqPool;
@@ -329,7 +337,7 @@ static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)
329
337
 
330
338
  static ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers)
331
339
  {
332
- return ZSTDMT_expandBufferPool(pool, nbWorkers);
340
+ return ZSTDMT_expandBufferPool(pool, SEQ_POOL_MAX_NB_BUFFERS(nbWorkers));
333
341
  }
334
342
 
335
343
 
@@ -936,7 +944,7 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
936
944
  mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);
937
945
  assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */
938
946
  mtctx->jobIDMask = nbJobs - 1;
939
- mtctx->bufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
947
+ mtctx->bufPool = ZSTDMT_createBufferPool(BUF_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);
940
948
  mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem);
941
949
  mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem);
942
950
  initError = ZSTDMT_serialState_init(&mtctx->serial);
@@ -1039,7 +1047,7 @@ static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
1039
1047
  {
1040
1048
  if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
1041
1049
  FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , "");
1042
- mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
1050
+ mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, BUF_POOL_MAX_NB_BUFFERS(nbWorkers));
1043
1051
  if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
1044
1052
  mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
1045
1053
  if (mtctx->cctxPool == NULL) return ERROR(memory_allocation);
@@ -65,8 +65,11 @@ size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
65
65
  * Private use only. Init streaming operation.
66
66
  * expects params to be valid.
67
67
  * must receive dict, or cdict, or none, but not both.
68
+ * mtctx can be freshly constructed or reused from a prior compression.
69
+ * If mtctx is reused, memory allocations from the prior compression may not be freed,
70
+ * even if they are not needed for the current compression.
68
71
  * @return : 0, or an error code */
69
- size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
72
+ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx,
70
73
  const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,
71
74
  const ZSTD_CDict* cdict,
72
75
  ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
@@ -664,7 +664,7 @@ size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize,
664
664
 
665
665
  #if ZSTD_ENABLE_ASM_X86_64_BMI2
666
666
 
667
- HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args);
667
+ HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
668
668
 
669
669
  static HUF_ASM_X86_64_BMI2_ATTRS
670
670
  size_t
@@ -1380,7 +1380,7 @@ size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize,
1380
1380
 
1381
1381
  #if ZSTD_ENABLE_ASM_X86_64_BMI2
1382
1382
 
1383
- HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args);
1383
+ HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
1384
1384
 
1385
1385
  static HUF_ASM_X86_64_BMI2_ATTRS size_t
1386
1386
  HUF_decompress4X2_usingDTable_internal_bmi2_asm(
@@ -1,14 +1,24 @@
1
- #include "../common/portability_macros.h"
1
+ /*
2
+ * Copyright (c) Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
2
10
 
3
- #if ZSTD_ENABLE_ASM_X86_64_BMI2
11
+ #include "../common/portability_macros.h"
4
12
 
5
13
  /* Stack marking
6
14
  * ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
7
15
  */
8
- #if defined(__linux__) && defined(__ELF__)
16
+ #if defined(__ELF__) && defined(__GNUC__)
9
17
  .section .note.GNU-stack,"",%progbits
10
18
  #endif
11
19
 
20
+ #if ZSTD_ENABLE_ASM_X86_64_BMI2
21
+
12
22
  /* Calling convention:
13
23
  *
14
24
  * %rdi contains the first argument: HUF_DecompressAsmArgs*.
@@ -20,6 +30,10 @@
20
30
  * TODO: Support Windows calling convention.
21
31
  */
22
32
 
33
+ ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
34
+ ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
35
+ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
36
+ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
23
37
  .global HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
24
38
  .global HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
25
39
  .global _HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
@@ -682,8 +682,8 @@ static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params,
682
682
 
683
683
  if (nbSeq >= 2) { /* rep offsets */
684
684
  const seqDef* const seq = seqStorePtr->sequencesStart;
685
- U32 offset1 = seq[0].offset - 3;
686
- U32 offset2 = seq[1].offset - 3;
685
+ U32 offset1 = seq[0].offBase - ZSTD_REP_NUM;
686
+ U32 offset2 = seq[1].offBase - ZSTD_REP_NUM;
687
687
  if (offset1 >= MAXREPOFFSET) offset1 = 0;
688
688
  if (offset2 >= MAXREPOFFSET) offset2 = 0;
689
689
  repOffsets[offset1] += 3;
@@ -74,7 +74,7 @@ extern "C" {
74
74
  /*------ Version ------*/
75
75
  #define ZSTD_VERSION_MAJOR 1
76
76
  #define ZSTD_VERSION_MINOR 5
77
- #define ZSTD_VERSION_RELEASE 1
77
+ #define ZSTD_VERSION_RELEASE 2
78
78
  #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
79
79
 
80
80
  /*! ZSTD_versionNumber() :
@@ -0,0 +1,14 @@
1
+ #include <common.h>
2
+ VALUE rb_mZstd;
3
+ void zstd_ruby_init(void);
4
+ void zstd_ruby_streaming_compress_init(void);
5
+ void zstd_ruby_streaming_decompress_init(void);
6
+
7
+ void
8
+ Init_zstdruby(void)
9
+ {
10
+ rb_mZstd = rb_define_module("Zstd");
11
+ zstd_ruby_init();
12
+ zstd_ruby_streaming_compress_init();
13
+ zstd_ruby_streaming_decompress_init();
14
+ }
@@ -0,0 +1,183 @@
1
+ #include <common.h>
2
+ #include <streaming_compress.h>
3
+
4
+ struct streaming_compress_t {
5
+ ZSTD_CCtx* ctx;
6
+ VALUE buf;
7
+ size_t buf_size;
8
+ };
9
+
10
+ static void
11
+ streaming_compress_mark(void *p)
12
+ {
13
+ struct streaming_compress_t *sc = p;
14
+ rb_gc_mark(sc->buf);
15
+ }
16
+
17
+ static void
18
+ streaming_compress_free(void *p)
19
+ {
20
+ struct streaming_compress_t *sc = p;
21
+ ZSTD_CCtx* ctx = sc->ctx;
22
+ if (ctx != NULL) {
23
+ ZSTD_freeCCtx(ctx);
24
+ }
25
+ xfree(sc);
26
+ }
27
+
28
+ static size_t
29
+ streaming_compress_memsize(const void *p)
30
+ {
31
+ return sizeof(struct streaming_compress_t);
32
+ }
33
+
34
+ static const rb_data_type_t streaming_compress_type = {
35
+ "streaming_compress",
36
+ { streaming_compress_mark, streaming_compress_free, streaming_compress_memsize, },
37
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
38
+ };
39
+
40
+ static VALUE
41
+ rb_streaming_compress_allocate(VALUE klass)
42
+ {
43
+ struct streaming_compress_t* sc;
44
+ VALUE obj = TypedData_Make_Struct(klass, struct streaming_compress_t, &streaming_compress_type, sc);
45
+ sc->ctx = NULL;
46
+ sc->buf = Qnil;
47
+ sc->buf_size = 0;
48
+ return obj;
49
+ }
50
+
51
+ static VALUE
52
+ rb_streaming_compress_initialize(int argc, VALUE *argv, VALUE obj)
53
+ {
54
+ VALUE compression_level_value;
55
+ rb_scan_args(argc, argv, "01", &compression_level_value);
56
+
57
+ int compression_level;
58
+ if (NIL_P(compression_level_value)) {
59
+ compression_level = ZSTD_CLEVEL_DEFAULT;
60
+ } else {
61
+ compression_level = NUM2INT(compression_level_value);
62
+ }
63
+
64
+ struct streaming_compress_t* sc;
65
+ TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
66
+ size_t const buffOutSize = ZSTD_CStreamOutSize();
67
+
68
+ ZSTD_CCtx* ctx = ZSTD_createCCtx();
69
+ if (ctx == NULL) {
70
+ rb_raise(rb_eRuntimeError, "%s", "ZSTD_createCCtx error");
71
+ }
72
+ ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, compression_level);
73
+ sc->ctx = ctx;
74
+ sc->buf = rb_str_new(NULL, buffOutSize);
75
+ sc->buf_size = buffOutSize;
76
+
77
+ return obj;
78
+ }
79
+
80
+ #define FIXNUMARG(val, ifnil) \
81
+ (NIL_P((val)) ? (ifnil) \
82
+ : (FIX2INT((val))))
83
+ #define ARG_CONTINUE(val) FIXNUMARG((val), ZSTD_e_continue)
84
+
85
+ static VALUE
86
+ no_compress(struct streaming_compress_t* sc, ZSTD_EndDirective endOp)
87
+ {
88
+ ZSTD_inBuffer input = { NULL, 0, 0 };
89
+ const char* output_data = RSTRING_PTR(sc->buf);
90
+ VALUE result = rb_str_new(0, 0);
91
+ size_t ret;
92
+ do {
93
+ ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
94
+
95
+ size_t const ret = ZSTD_compressStream2(sc->ctx, &output, &input, endOp);
96
+ if (ZSTD_isError(ret)) {
97
+ rb_raise(rb_eRuntimeError, "flush error error code: %s", ZSTD_getErrorName(ret));
98
+ }
99
+ rb_str_cat(result, output.dst, output.pos);
100
+ } while (ret > 0);
101
+ return result;
102
+ }
103
+
104
+ static VALUE
105
+ rb_streaming_compress_compress(VALUE obj, VALUE src)
106
+ {
107
+ StringValue(src);
108
+ const char* input_data = RSTRING_PTR(src);
109
+ size_t input_size = RSTRING_LEN(src);
110
+ ZSTD_inBuffer input = { input_data, input_size, 0 };
111
+
112
+ struct streaming_compress_t* sc;
113
+ TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
114
+ const char* output_data = RSTRING_PTR(sc->buf);
115
+ VALUE result = rb_str_new(0, 0);
116
+ while (input.pos < input.size) {
117
+ ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
118
+ size_t const ret = ZSTD_compressStream2(sc->ctx, &output, &input, ZSTD_e_continue);
119
+ if (ZSTD_isError(ret)) {
120
+ rb_raise(rb_eRuntimeError, "compress error error code: %s", ZSTD_getErrorName(ret));
121
+ }
122
+ rb_str_cat(result, output.dst, output.pos);
123
+ }
124
+ return result;
125
+ }
126
+
127
+ static VALUE
128
+ rb_streaming_compress_addstr(VALUE obj, VALUE src)
129
+ {
130
+ StringValue(src);
131
+ const char* input_data = RSTRING_PTR(src);
132
+ size_t input_size = RSTRING_LEN(src);
133
+ ZSTD_inBuffer input = { input_data, input_size, 0 };
134
+
135
+ struct streaming_compress_t* sc;
136
+ TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
137
+ const char* output_data = RSTRING_PTR(sc->buf);
138
+
139
+ while (input.pos < input.size) {
140
+ ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
141
+ size_t const result = ZSTD_compressStream2(sc->ctx, &output, &input, ZSTD_e_continue);
142
+ if (ZSTD_isError(result)) {
143
+ rb_raise(rb_eRuntimeError, "compress error error code: %s", ZSTD_getErrorName(result));
144
+ }
145
+ }
146
+ return obj;
147
+ }
148
+
149
+ static VALUE
150
+ rb_streaming_compress_flush(VALUE obj)
151
+ {
152
+ struct streaming_compress_t* sc;
153
+ TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
154
+ VALUE result = no_compress(sc, ZSTD_e_flush);
155
+ return result;
156
+ }
157
+
158
+ static VALUE
159
+ rb_streaming_compress_finish(VALUE obj)
160
+ {
161
+ struct streaming_compress_t* sc;
162
+ TypedData_Get_Struct(obj, struct streaming_compress_t, &streaming_compress_type, sc);
163
+ VALUE result = no_compress(sc, ZSTD_e_end);
164
+ return result;
165
+ }
166
+
167
+ extern VALUE rb_mZstd, cStreamingCompress;
168
+ void
169
+ zstd_ruby_streaming_compress_init(void)
170
+ {
171
+ VALUE cStreamingCompress = rb_define_class_under(rb_mZstd, "StreamingCompress", rb_cObject);
172
+ rb_define_alloc_func(cStreamingCompress, rb_streaming_compress_allocate);
173
+ rb_define_method(cStreamingCompress, "initialize", rb_streaming_compress_initialize, -1);
174
+ rb_define_method(cStreamingCompress, "compress", rb_streaming_compress_compress, 1);
175
+ rb_define_method(cStreamingCompress, "<<", rb_streaming_compress_addstr, 1);
176
+ rb_define_method(cStreamingCompress, "flush", rb_streaming_compress_flush, 0);
177
+ rb_define_method(cStreamingCompress, "finish", rb_streaming_compress_finish, 0);
178
+
179
+ rb_define_const(cStreamingCompress, "CONTINUE", INT2FIX(ZSTD_e_continue));
180
+ rb_define_const(cStreamingCompress, "FLUSH", INT2FIX(ZSTD_e_flush));
181
+ rb_define_const(cStreamingCompress, "END", INT2FIX(ZSTD_e_end));
182
+ }
183
+
@@ -0,0 +1,5 @@
1
+ #if !defined(STREAMING_COMPRESS_H)
2
+ #define STREAMING_COMPRESS_H
3
+
4
+
5
+ #endif // STREAMING_COMPRESS_H