zstd-ruby 1.3.8.0 → 1.4.5.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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -5
  3. data/README.md +1 -1
  4. data/ext/zstdruby/libzstd/Makefile +133 -61
  5. data/ext/zstdruby/libzstd/README.md +51 -18
  6. data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
  7. data/ext/zstdruby/libzstd/common/compiler.h +41 -6
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  10. data/ext/zstdruby/libzstd/common/debug.h +11 -31
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
  12. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +6 -2
  14. data/ext/zstdruby/libzstd/common/fse.h +13 -33
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
  16. data/ext/zstdruby/libzstd/common/huf.h +15 -33
  17. data/ext/zstdruby/libzstd/common/mem.h +75 -2
  18. data/ext/zstdruby/libzstd/common/pool.c +8 -4
  19. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  20. data/ext/zstdruby/libzstd/common/threading.c +52 -6
  21. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  22. data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
  23. data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
  27. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
  28. data/ext/zstdruby/libzstd/compress/hist.c +15 -35
  29. data/ext/zstdruby/libzstd/compress/hist.h +12 -32
  30. data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
  31. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
  32. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
  33. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
  41. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  42. data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
  43. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  44. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
  45. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
  46. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
  47. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
  49. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
  51. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
  52. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
  53. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
  54. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  55. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
  56. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
  57. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
  59. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  60. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  61. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  62. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
  65. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
  66. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
  67. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
  68. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  69. data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
  70. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
  71. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
  72. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
  73. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
  74. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
  75. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
  76. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
  77. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
  78. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
  79. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
  80. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
  81. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
  82. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
  83. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
  84. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
  85. data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
  86. data/ext/zstdruby/libzstd/zstd.h +921 -597
  87. data/lib/zstd-ruby/version.rb +1 -1
  88. data/zstd-ruby.gemspec +2 -2
  89. metadata +19 -14
  90. data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
@@ -1,10 +1,11 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
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.
8
9
  */
9
10
 
10
11
  #ifndef ZSTD_LDM_H
@@ -15,7 +16,7 @@ extern "C" {
15
16
  #endif
16
17
 
17
18
  #include "zstd_compress_internal.h" /* ldmParams_t, U32 */
18
- #include "zstd.h" /* ZSTD_CCtx, size_t */
19
+ #include "../zstd.h" /* ZSTD_CCtx, size_t */
19
20
 
20
21
  /*-*************************************
21
22
  * Long distance matching
@@ -23,6 +24,10 @@ extern "C" {
23
24
 
24
25
  #define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT
25
26
 
27
+ void ZSTD_ldm_fillHashTable(
28
+ ldmState_t* state, const BYTE* ip,
29
+ const BYTE* iend, ldmParams_t const* params);
30
+
26
31
  /**
27
32
  * ZSTD_ldm_generateSequences():
28
33
  *
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -64,9 +64,15 @@ MEM_STATIC double ZSTD_fCost(U32 price)
64
64
  }
65
65
  #endif
66
66
 
67
+ static int ZSTD_compressedLiterals(optState_t const* const optPtr)
68
+ {
69
+ return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
70
+ }
71
+
67
72
  static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
68
73
  {
69
- optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
74
+ if (ZSTD_compressedLiterals(optPtr))
75
+ optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
70
76
  optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
71
77
  optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
72
78
  optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);
@@ -99,6 +105,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
99
105
  const BYTE* const src, size_t const srcSize,
100
106
  int const optLevel)
101
107
  {
108
+ int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
102
109
  DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
103
110
  optPtr->priceType = zop_dynamic;
104
111
 
@@ -113,9 +120,10 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
113
120
  /* huffman table presumed generated by dictionary */
114
121
  optPtr->priceType = zop_dynamic;
115
122
 
116
- assert(optPtr->litFreq != NULL);
117
- optPtr->litSum = 0;
118
- { unsigned lit;
123
+ if (compressedLiterals) {
124
+ unsigned lit;
125
+ assert(optPtr->litFreq != NULL);
126
+ optPtr->litSum = 0;
119
127
  for (lit=0; lit<=MaxLit; lit++) {
120
128
  U32 const scaleLog = 11; /* scale to 2K */
121
129
  U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
@@ -163,10 +171,11 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
163
171
  } else { /* not a dictionary */
164
172
 
165
173
  assert(optPtr->litFreq != NULL);
166
- { unsigned lit = MaxLit;
174
+ if (compressedLiterals) {
175
+ unsigned lit = MaxLit;
167
176
  HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
177
+ optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
168
178
  }
169
- optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
170
179
 
171
180
  { unsigned ll;
172
181
  for (ll=0; ll<=MaxLL; ll++)
@@ -190,7 +199,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
190
199
 
191
200
  } else { /* new block : re-use previous statistics, scaled down */
192
201
 
193
- optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
202
+ if (compressedLiterals)
203
+ optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
194
204
  optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
195
205
  optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
196
206
  optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
@@ -207,6 +217,10 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
207
217
  int optLevel)
208
218
  {
209
219
  if (litLength == 0) return 0;
220
+
221
+ if (!ZSTD_compressedLiterals(optPtr))
222
+ return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
223
+
210
224
  if (optPtr->priceType == zop_predef)
211
225
  return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
212
226
 
@@ -235,40 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
235
249
  }
236
250
  }
237
251
 
238
- /* ZSTD_litLengthContribution() :
239
- * @return ( cost(litlength) - cost(0) )
240
- * this value can then be added to rawLiteralsCost()
241
- * to provide a cost which is directly comparable to a match ending at same position */
242
- static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
243
- {
244
- if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
245
-
246
- /* dynamic statistics */
247
- { U32 const llCode = ZSTD_LLcode(litLength);
248
- int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
249
- + WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
250
- - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
251
- #if 1
252
- return contribution;
253
- #else
254
- return MAX(0, contribution); /* sometimes better, sometimes not ... */
255
- #endif
256
- }
257
- }
258
-
259
- /* ZSTD_literalsContribution() :
260
- * creates a fake cost for the literals part of a sequence
261
- * which can be compared to the ending cost of a match
262
- * should a new match start at this position */
263
- static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
264
- const optState_t* const optPtr,
265
- int optLevel)
266
- {
267
- int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
268
- + ZSTD_litLengthContribution(litLength, optPtr, optLevel);
269
- return contribution;
270
- }
271
-
272
252
  /* ZSTD_getMatchPrice() :
273
253
  * Provides the cost of the match part (offset + matchLength) of a sequence
274
254
  * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
@@ -310,7 +290,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
310
290
  U32 offsetCode, U32 matchLength)
311
291
  {
312
292
  /* literals */
313
- { U32 u;
293
+ if (ZSTD_compressedLiterals(optPtr)) {
294
+ U32 u;
314
295
  for (u=0; u < litLength; u++)
315
296
  optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
316
297
  optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
@@ -357,13 +338,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
357
338
 
358
339
  /* Update hashTable3 up to ip (excluded)
359
340
  Assumption : always within prefix (i.e. not within extDict) */
360
- static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* const ip)
341
+ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
342
+ U32* nextToUpdate3,
343
+ const BYTE* const ip)
361
344
  {
362
345
  U32* const hashTable3 = ms->hashTable3;
363
346
  U32 const hashLog3 = ms->hashLog3;
364
347
  const BYTE* const base = ms->window.base;
365
- U32 idx = ms->nextToUpdate3;
366
- U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
348
+ U32 idx = *nextToUpdate3;
349
+ U32 const target = (U32)(ip - base);
367
350
  size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
368
351
  assert(hashLog3 > 0);
369
352
 
@@ -372,6 +355,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
372
355
  idx++;
373
356
  }
374
357
 
358
+ *nextToUpdate3 = target;
375
359
  return hashTable3[hash3];
376
360
  }
377
361
 
@@ -488,9 +472,11 @@ static U32 ZSTD_insertBt1(
488
472
  } }
489
473
 
490
474
  *smallerPtr = *largerPtr = 0;
491
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
492
- assert(matchEndIdx > current + 8);
493
- return matchEndIdx - (current + 8);
475
+ { U32 positions = 0;
476
+ if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */
477
+ assert(matchEndIdx > current + 8);
478
+ return MAX(positions, matchEndIdx - (current + 8));
479
+ }
494
480
  }
495
481
 
496
482
  FORCE_INLINE_TEMPLATE
@@ -505,8 +491,13 @@ void ZSTD_updateTree_internal(
505
491
  DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
506
492
  idx, target, dictMode);
507
493
 
508
- while(idx < target)
509
- idx += ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
494
+ while(idx < target) {
495
+ U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
496
+ assert(idx < (U32)(idx + forward));
497
+ idx += forward;
498
+ }
499
+ assert((size_t)(ip - base) <= (size_t)(U32)(-1));
500
+ assert((size_t)(iend - base) <= (size_t)(U32)(-1));
510
501
  ms->nextToUpdate = target;
511
502
  }
512
503
 
@@ -516,11 +507,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
516
507
 
517
508
  FORCE_INLINE_TEMPLATE
518
509
  U32 ZSTD_insertBtAndGetAllMatches (
510
+ ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
519
511
  ZSTD_matchState_t* ms,
512
+ U32* nextToUpdate3,
520
513
  const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
521
- U32 rep[ZSTD_REP_NUM],
514
+ const U32 rep[ZSTD_REP_NUM],
522
515
  U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
523
- ZSTD_match_t* matches,
524
516
  const U32 lengthToBeat,
525
517
  U32 const mls /* template */)
526
518
  {
@@ -541,8 +533,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
541
533
  U32 const dictLimit = ms->window.dictLimit;
542
534
  const BYTE* const dictEnd = dictBase + dictLimit;
543
535
  const BYTE* const prefixStart = base + dictLimit;
544
- U32 const btLow = btMask >= current ? 0 : current - btMask;
545
- U32 const windowLow = ms->window.lowLimit;
536
+ U32 const btLow = (btMask >= current) ? 0 : current - btMask;
537
+ U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog);
546
538
  U32 const matchLow = windowLow ? windowLow : 1;
547
539
  U32* smallerPtr = bt + 2*(current&btMask);
548
540
  U32* largerPtr = bt + 2*(current&btMask) + 1;
@@ -577,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
577
569
  U32 repLen = 0;
578
570
  assert(current >= dictLimit);
579
571
  if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
580
- if (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch)) {
572
+ /* We must validate the repcode offset because when we're using a dictionary the
573
+ * valid offset range shrinks when the dictionary goes out of bounds.
574
+ */
575
+ if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) {
581
576
  repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
582
577
  }
583
578
  } else { /* repIndex < dictLimit || repIndex >= current */
@@ -612,7 +607,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
612
607
 
613
608
  /* HC3 match finder */
614
609
  if ((mls == 3) /*static*/ && (bestLength < mls)) {
615
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
610
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
616
611
  if ((matchIndex3 >= matchLow)
617
612
  & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
618
613
  size_t mlen;
@@ -638,9 +633,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
638
633
  (ip+mlen == iLimit) ) { /* best possible length */
639
634
  ms->nextToUpdate = current+1; /* skip insertion */
640
635
  return 1;
641
- }
642
- }
643
- }
636
+ } } }
644
637
  /* no dictMatchState lookup: dicts don't have a populated HC3 table */
645
638
  }
646
639
 
@@ -648,19 +641,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
648
641
 
649
642
  while (nbCompares-- && (matchIndex >= matchLow)) {
650
643
  U32* const nextPtr = bt + 2*(matchIndex & btMask);
651
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
652
644
  const BYTE* match;
645
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
653
646
  assert(current > matchIndex);
654
647
 
655
648
  if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
656
649
  assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
657
650
  match = base + matchIndex;
651
+ if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
658
652
  matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
659
653
  } else {
660
654
  match = dictBase + matchIndex;
655
+ assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
661
656
  matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
662
657
  if (matchIndex+matchLength >= dictLimit)
663
- match = base + matchIndex; /* prepare for match[matchLength] */
658
+ match = base + matchIndex; /* prepare for match[matchLength] read */
664
659
  }
665
660
 
666
661
  if (matchLength > bestLength) {
@@ -745,10 +740,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
745
740
 
746
741
 
747
742
  FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
743
+ ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
748
744
  ZSTD_matchState_t* ms,
745
+ U32* nextToUpdate3,
749
746
  const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
750
- U32 rep[ZSTD_REP_NUM], U32 const ll0,
751
- ZSTD_match_t* matches, U32 const lengthToBeat)
747
+ const U32 rep[ZSTD_REP_NUM],
748
+ U32 const ll0,
749
+ U32 const lengthToBeat)
752
750
  {
753
751
  const ZSTD_compressionParameters* const cParams = &ms->cParams;
754
752
  U32 const matchLengthSearch = cParams->minMatch;
@@ -757,12 +755,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
757
755
  ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
758
756
  switch(matchLengthSearch)
759
757
  {
760
- case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
758
+ case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
761
759
  default :
762
- case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
763
- case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
760
+ case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
761
+ case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
764
762
  case 7 :
765
- case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
763
+ case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
766
764
  }
767
765
  }
768
766
 
@@ -770,30 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
770
768
  /*-*******************************
771
769
  * Optimal parser
772
770
  *********************************/
773
- typedef struct repcodes_s {
774
- U32 rep[3];
775
- } repcodes_t;
776
-
777
- static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
778
- {
779
- repcodes_t newReps;
780
- if (offset >= ZSTD_REP_NUM) { /* full offset */
781
- newReps.rep[2] = rep[1];
782
- newReps.rep[1] = rep[0];
783
- newReps.rep[0] = offset - ZSTD_REP_MOVE;
784
- } else { /* repcode */
785
- U32 const repCode = offset + ll0;
786
- if (repCode > 0) { /* note : if repCode==0, no change */
787
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
788
- newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
789
- newReps.rep[1] = rep[0];
790
- newReps.rep[0] = currentOffset;
791
- } else { /* repCode == 0 */
792
- memcpy(&newReps, rep, sizeof(newReps));
793
- }
794
- }
795
- return newReps;
796
- }
797
771
 
798
772
 
799
773
  static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
@@ -810,7 +784,7 @@ listStats(const U32* table, int lastEltID)
810
784
  int enb;
811
785
  for (enb=0; enb < nbElts; enb++) {
812
786
  (void)table;
813
- //RAWLOG(2, "%3i:%3i, ", enb, table[enb]);
787
+ /* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
814
788
  RAWLOG(2, "%4i,", table[enb]);
815
789
  }
816
790
  RAWLOG(2, " \n");
@@ -838,6 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
838
812
 
839
813
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
840
814
  U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
815
+ U32 nextToUpdate3 = ms->nextToUpdate;
841
816
 
842
817
  ZSTD_optimal_t* const opt = optStatePtr->priceTable;
843
818
  ZSTD_match_t* const matches = optStatePtr->matchTable;
@@ -847,7 +822,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
847
822
  DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
848
823
  (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
849
824
  assert(optLevel <= 2);
850
- ms->nextToUpdate3 = ms->nextToUpdate;
851
825
  ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
852
826
  ip += (ip==prefixStart);
853
827
 
@@ -858,19 +832,24 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
858
832
  /* find first match */
859
833
  { U32 const litlen = (U32)(ip - anchor);
860
834
  U32 const ll0 = !litlen;
861
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
835
+ U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
862
836
  if (!nbMatches) { ip++; continue; }
863
837
 
864
838
  /* initialize opt[0] */
865
839
  { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
866
840
  opt[0].mlen = 0; /* means is_a_literal */
867
841
  opt[0].litlen = litlen;
868
- opt[0].price = ZSTD_literalsContribution(anchor, litlen, optStatePtr, optLevel);
842
+ /* We don't need to include the actual price of the literals because
843
+ * it is static for the duration of the forward pass, and is included
844
+ * in every price. We include the literal length to avoid negative
845
+ * prices when we subtract the previous literal length.
846
+ */
847
+ opt[0].price = ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
869
848
 
870
849
  /* large match -> immediate encoding */
871
850
  { U32 const maxML = matches[nbMatches-1].len;
872
851
  U32 const maxOffset = matches[nbMatches-1].off;
873
- DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new serie",
852
+ DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
874
853
  nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
875
854
 
876
855
  if (maxML > sufficient_len) {
@@ -894,7 +873,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
894
873
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
895
874
  U32 const offset = matches[matchNb].off;
896
875
  U32 const end = matches[matchNb].len;
897
- repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
898
876
  for ( ; pos <= end ; pos++ ) {
899
877
  U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
900
878
  U32 const sequencePrice = literalsPrice + matchPrice;
@@ -904,8 +882,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
904
882
  opt[pos].off = offset;
905
883
  opt[pos].litlen = litlen;
906
884
  opt[pos].price = sequencePrice;
907
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
908
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
909
885
  } }
910
886
  last_pos = pos-1;
911
887
  }
@@ -932,7 +908,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
932
908
  opt[cur].off = 0;
933
909
  opt[cur].litlen = litlen;
934
910
  opt[cur].price = price;
935
- memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
936
911
  } else {
937
912
  DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
938
913
  inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
@@ -940,6 +915,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
940
915
  }
941
916
  }
942
917
 
918
+ /* Set the repcodes of the current position. We must do it here
919
+ * because we rely on the repcodes of the 2nd to last sequence being
920
+ * correct to set the next chunks repcodes during the backward
921
+ * traversal.
922
+ */
923
+ ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t));
924
+ assert(cur >= opt[cur].mlen);
925
+ if (opt[cur].mlen != 0) {
926
+ U32 const prev = cur - opt[cur].mlen;
927
+ repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
928
+ memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
929
+ } else {
930
+ memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
931
+ }
932
+
943
933
  /* last match must start at a minimum distance of 8 from oend */
944
934
  if (inr > ilimit) continue;
945
935
 
@@ -955,7 +945,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
955
945
  U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
956
946
  U32 const previousPrice = opt[cur].price;
957
947
  U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
958
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
948
+ U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
959
949
  U32 matchNb;
960
950
  if (!nbMatches) {
961
951
  DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -980,7 +970,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
980
970
  /* set prices using matches found at position == cur */
981
971
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
982
972
  U32 const offset = matches[matchNb].off;
983
- repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
984
973
  U32 const lastML = matches[matchNb].len;
985
974
  U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
986
975
  U32 mlen;
@@ -1000,8 +989,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1000
989
  opt[pos].off = offset;
1001
990
  opt[pos].litlen = litlen;
1002
991
  opt[pos].price = price;
1003
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
1004
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
1005
992
  } else {
1006
993
  DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
1007
994
  pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
@@ -1017,6 +1004,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1017
1004
  _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1018
1005
  assert(opt[0].mlen == 0);
1019
1006
 
1007
+ /* Set the next chunk's repcodes based on the repcodes of the beginning
1008
+ * of the last match, and the last sequence. This avoids us having to
1009
+ * update them while traversing the sequences.
1010
+ */
1011
+ if (lastSequence.mlen != 0) {
1012
+ repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
1013
+ memcpy(rep, &reps, sizeof(reps));
1014
+ } else {
1015
+ memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
1016
+ }
1017
+
1020
1018
  { U32 const storeEnd = cur + 1;
1021
1019
  U32 storeStart = storeEnd;
1022
1020
  U32 seqPos = cur;
@@ -1053,33 +1051,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1053
1051
  continue; /* will finish */
1054
1052
  }
1055
1053
 
1056
- /* repcodes update : like ZSTD_updateRep(), but update in place */
1057
- if (offCode >= ZSTD_REP_NUM) { /* full offset */
1058
- rep[2] = rep[1];
1059
- rep[1] = rep[0];
1060
- rep[0] = offCode - ZSTD_REP_MOVE;
1061
- } else { /* repcode */
1062
- U32 const repCode = offCode + (llen==0);
1063
- if (repCode) { /* note : if repCode==0, no change */
1064
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
1065
- if (repCode >= 2) rep[2] = rep[1];
1066
- rep[1] = rep[0];
1067
- rep[0] = currentOffset;
1068
- } }
1069
-
1070
1054
  assert(anchor + llen <= iend);
1071
1055
  ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
1072
- ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
1056
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
1073
1057
  anchor += advance;
1074
1058
  ip = anchor;
1075
1059
  } }
1076
1060
  ZSTD_setBasePrices(optStatePtr, optLevel);
1077
1061
  }
1078
-
1079
1062
  } /* while (ip < ilimit) */
1080
1063
 
1081
1064
  /* Return the last literals size */
1082
- return iend - anchor;
1065
+ return (size_t)(iend - anchor);
1083
1066
  }
1084
1067
 
1085
1068
 
@@ -1108,7 +1091,8 @@ static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
1108
1091
  /* used in 2-pass strategy */
1109
1092
  MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
1110
1093
  {
1111
- optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
1094
+ if (ZSTD_compressedLiterals(optPtr))
1095
+ optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
1112
1096
  optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
1113
1097
  optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
1114
1098
  optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
@@ -1117,7 +1101,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
1117
1101
  /* ZSTD_initStats_ultra():
1118
1102
  * make a first compression pass, just to seed stats with more accurate starting values.
1119
1103
  * only works on first block, with no dictionary and no ldm.
1120
- * this function cannot error, hence its constract must be respected.
1104
+ * this function cannot error, hence its contract must be respected.
1121
1105
  */
1122
1106
  static void
1123
1107
  ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
@@ -1142,7 +1126,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
1142
1126
  ms->window.dictLimit += (U32)srcSize;
1143
1127
  ms->window.lowLimit = ms->window.dictLimit;
1144
1128
  ms->nextToUpdate = ms->window.dictLimit;
1145
- ms->nextToUpdate3 = ms->window.dictLimit;
1146
1129
 
1147
1130
  /* re-inforce weight of collected statistics */
1148
1131
  ZSTD_upscaleStats(&ms->opt);