zstdlib 0.2.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +30 -1
  3. data/README.md +2 -2
  4. data/Rakefile +1 -1
  5. data/ext/zstdlib/extconf.rb +3 -3
  6. data/ext/zstdlib/ruby/zlib-2.7/zstdlib.c +4895 -0
  7. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/bitstream.h +38 -39
  8. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/compiler.h +40 -5
  9. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/cpu.h +1 -1
  10. data/ext/zstdlib/zstd-1.4.5/lib/common/debug.c +24 -0
  11. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/debug.h +11 -31
  12. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/entropy_common.c +13 -33
  13. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/error_private.c +2 -1
  14. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/error_private.h +6 -2
  15. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/fse.h +12 -32
  16. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/fse_decompress.c +12 -35
  17. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/huf.h +15 -33
  18. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/mem.h +75 -2
  19. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/pool.c +8 -4
  20. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/pool.h +2 -2
  21. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/threading.c +50 -4
  22. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/threading.h +36 -4
  23. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/xxhash.c +23 -35
  24. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/xxhash.h +11 -31
  25. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_common.c +1 -1
  26. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_errors.h +2 -1
  27. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_internal.h +154 -26
  28. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/fse_compress.c +17 -40
  29. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/hist.c +15 -35
  30. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/hist.h +12 -32
  31. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/huf_compress.c +92 -92
  32. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_compress.c +1191 -1330
  33. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_compress_internal.h +317 -55
  34. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_literals.c +158 -0
  35. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_literals.h +29 -0
  36. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_sequences.c +419 -0
  37. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_sequences.h +54 -0
  38. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_superblock.c +845 -0
  39. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_superblock.h +32 -0
  40. data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_cwksp.h +525 -0
  41. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_double_fast.c +65 -43
  42. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_double_fast.h +2 -2
  43. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_fast.c +92 -66
  44. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_fast.h +2 -2
  45. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_lazy.c +74 -42
  46. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_lazy.h +1 -1
  47. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_ldm.c +32 -10
  48. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_ldm.h +7 -2
  49. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_opt.c +81 -114
  50. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_opt.h +1 -1
  51. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstdmt_compress.c +95 -51
  52. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstdmt_compress.h +3 -2
  53. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/huf_decompress.c +76 -60
  54. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_ddict.c +12 -8
  55. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_ddict.h +2 -2
  56. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress.c +292 -172
  57. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_block.c +459 -338
  58. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_block.h +3 -3
  59. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_internal.h +18 -4
  60. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/zstd.h +265 -88
  61. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzclose.c +1 -1
  62. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzcompatibility.h +1 -1
  63. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzguts.h +0 -0
  64. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzlib.c +9 -9
  65. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzread.c +16 -8
  66. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzwrite.c +8 -8
  67. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/zstd_zlibwrapper.c +16 -12
  68. data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/zstd_zlibwrapper.h +1 -1
  69. metadata +69 -62
  70. data/ext/zstdlib/zstd-1.4.0/lib/common/debug.c +0 -44
@@ -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
@@ -249,40 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
249
249
  }
250
250
  }
251
251
 
252
- /* ZSTD_litLengthContribution() :
253
- * @return ( cost(litlength) - cost(0) )
254
- * this value can then be added to rawLiteralsCost()
255
- * to provide a cost which is directly comparable to a match ending at same position */
256
- static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
257
- {
258
- if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
259
-
260
- /* dynamic statistics */
261
- { U32 const llCode = ZSTD_LLcode(litLength);
262
- int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
263
- + WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
264
- - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
265
- #if 1
266
- return contribution;
267
- #else
268
- return MAX(0, contribution); /* sometimes better, sometimes not ... */
269
- #endif
270
- }
271
- }
272
-
273
- /* ZSTD_literalsContribution() :
274
- * creates a fake cost for the literals part of a sequence
275
- * which can be compared to the ending cost of a match
276
- * should a new match start at this position */
277
- static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
278
- const optState_t* const optPtr,
279
- int optLevel)
280
- {
281
- int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
282
- + ZSTD_litLengthContribution(litLength, optPtr, optLevel);
283
- return contribution;
284
- }
285
-
286
252
  /* ZSTD_getMatchPrice() :
287
253
  * Provides the cost of the match part (offset + matchLength) of a sequence
288
254
  * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
@@ -372,13 +338,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
372
338
 
373
339
  /* Update hashTable3 up to ip (excluded)
374
340
  Assumption : always within prefix (i.e. not within extDict) */
375
- 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)
376
344
  {
377
345
  U32* const hashTable3 = ms->hashTable3;
378
346
  U32 const hashLog3 = ms->hashLog3;
379
347
  const BYTE* const base = ms->window.base;
380
- U32 idx = ms->nextToUpdate3;
381
- U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
348
+ U32 idx = *nextToUpdate3;
349
+ U32 const target = (U32)(ip - base);
382
350
  size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
383
351
  assert(hashLog3 > 0);
384
352
 
@@ -387,6 +355,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
387
355
  idx++;
388
356
  }
389
357
 
358
+ *nextToUpdate3 = target;
390
359
  return hashTable3[hash3];
391
360
  }
392
361
 
@@ -503,9 +472,11 @@ static U32 ZSTD_insertBt1(
503
472
  } }
504
473
 
505
474
  *smallerPtr = *largerPtr = 0;
506
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
507
- assert(matchEndIdx > current + 8);
508
- 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
+ }
509
480
  }
510
481
 
511
482
  FORCE_INLINE_TEMPLATE
@@ -520,8 +491,13 @@ void ZSTD_updateTree_internal(
520
491
  DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
521
492
  idx, target, dictMode);
522
493
 
523
- while(idx < target)
524
- 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));
525
501
  ms->nextToUpdate = target;
526
502
  }
527
503
 
@@ -531,11 +507,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
531
507
 
532
508
  FORCE_INLINE_TEMPLATE
533
509
  U32 ZSTD_insertBtAndGetAllMatches (
510
+ ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
534
511
  ZSTD_matchState_t* ms,
512
+ U32* nextToUpdate3,
535
513
  const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
536
- U32 rep[ZSTD_REP_NUM],
514
+ const U32 rep[ZSTD_REP_NUM],
537
515
  U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
538
- ZSTD_match_t* matches,
539
516
  const U32 lengthToBeat,
540
517
  U32 const mls /* template */)
541
518
  {
@@ -556,8 +533,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
556
533
  U32 const dictLimit = ms->window.dictLimit;
557
534
  const BYTE* const dictEnd = dictBase + dictLimit;
558
535
  const BYTE* const prefixStart = base + dictLimit;
559
- U32 const btLow = btMask >= current ? 0 : current - btMask;
560
- 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);
561
538
  U32 const matchLow = windowLow ? windowLow : 1;
562
539
  U32* smallerPtr = bt + 2*(current&btMask);
563
540
  U32* largerPtr = bt + 2*(current&btMask) + 1;
@@ -592,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
592
569
  U32 repLen = 0;
593
570
  assert(current >= dictLimit);
594
571
  if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
595
- 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))) {
596
576
  repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
597
577
  }
598
578
  } else { /* repIndex < dictLimit || repIndex >= current */
@@ -627,7 +607,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
627
607
 
628
608
  /* HC3 match finder */
629
609
  if ((mls == 3) /*static*/ && (bestLength < mls)) {
630
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
610
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
631
611
  if ((matchIndex3 >= matchLow)
632
612
  & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
633
613
  size_t mlen;
@@ -653,9 +633,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
653
633
  (ip+mlen == iLimit) ) { /* best possible length */
654
634
  ms->nextToUpdate = current+1; /* skip insertion */
655
635
  return 1;
656
- }
657
- }
658
- }
636
+ } } }
659
637
  /* no dictMatchState lookup: dicts don't have a populated HC3 table */
660
638
  }
661
639
 
@@ -663,19 +641,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
663
641
 
664
642
  while (nbCompares-- && (matchIndex >= matchLow)) {
665
643
  U32* const nextPtr = bt + 2*(matchIndex & btMask);
666
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
667
644
  const BYTE* match;
645
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
668
646
  assert(current > matchIndex);
669
647
 
670
648
  if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
671
649
  assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
672
650
  match = base + matchIndex;
651
+ if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
673
652
  matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
674
653
  } else {
675
654
  match = dictBase + matchIndex;
655
+ assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
676
656
  matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
677
657
  if (matchIndex+matchLength >= dictLimit)
678
- match = base + matchIndex; /* prepare for match[matchLength] */
658
+ match = base + matchIndex; /* prepare for match[matchLength] read */
679
659
  }
680
660
 
681
661
  if (matchLength > bestLength) {
@@ -760,10 +740,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
760
740
 
761
741
 
762
742
  FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
743
+ ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
763
744
  ZSTD_matchState_t* ms,
745
+ U32* nextToUpdate3,
764
746
  const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
765
- U32 rep[ZSTD_REP_NUM], U32 const ll0,
766
- ZSTD_match_t* matches, U32 const lengthToBeat)
747
+ const U32 rep[ZSTD_REP_NUM],
748
+ U32 const ll0,
749
+ U32 const lengthToBeat)
767
750
  {
768
751
  const ZSTD_compressionParameters* const cParams = &ms->cParams;
769
752
  U32 const matchLengthSearch = cParams->minMatch;
@@ -772,12 +755,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
772
755
  ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
773
756
  switch(matchLengthSearch)
774
757
  {
775
- 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);
776
759
  default :
777
- case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
778
- 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);
779
762
  case 7 :
780
- 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);
781
764
  }
782
765
  }
783
766
 
@@ -785,30 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
785
768
  /*-*******************************
786
769
  * Optimal parser
787
770
  *********************************/
788
- typedef struct repcodes_s {
789
- U32 rep[3];
790
- } repcodes_t;
791
-
792
- static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
793
- {
794
- repcodes_t newReps;
795
- if (offset >= ZSTD_REP_NUM) { /* full offset */
796
- newReps.rep[2] = rep[1];
797
- newReps.rep[1] = rep[0];
798
- newReps.rep[0] = offset - ZSTD_REP_MOVE;
799
- } else { /* repcode */
800
- U32 const repCode = offset + ll0;
801
- if (repCode > 0) { /* note : if repCode==0, no change */
802
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
803
- newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
804
- newReps.rep[1] = rep[0];
805
- newReps.rep[0] = currentOffset;
806
- } else { /* repCode == 0 */
807
- memcpy(&newReps, rep, sizeof(newReps));
808
- }
809
- }
810
- return newReps;
811
- }
812
771
 
813
772
 
814
773
  static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
@@ -825,7 +784,7 @@ listStats(const U32* table, int lastEltID)
825
784
  int enb;
826
785
  for (enb=0; enb < nbElts; enb++) {
827
786
  (void)table;
828
- //RAWLOG(2, "%3i:%3i, ", enb, table[enb]);
787
+ /* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
829
788
  RAWLOG(2, "%4i,", table[enb]);
830
789
  }
831
790
  RAWLOG(2, " \n");
@@ -853,6 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
853
812
 
854
813
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
855
814
  U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
815
+ U32 nextToUpdate3 = ms->nextToUpdate;
856
816
 
857
817
  ZSTD_optimal_t* const opt = optStatePtr->priceTable;
858
818
  ZSTD_match_t* const matches = optStatePtr->matchTable;
@@ -862,7 +822,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
862
822
  DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
863
823
  (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
864
824
  assert(optLevel <= 2);
865
- ms->nextToUpdate3 = ms->nextToUpdate;
866
825
  ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
867
826
  ip += (ip==prefixStart);
868
827
 
@@ -873,14 +832,19 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
873
832
  /* find first match */
874
833
  { U32 const litlen = (U32)(ip - anchor);
875
834
  U32 const ll0 = !litlen;
876
- 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);
877
836
  if (!nbMatches) { ip++; continue; }
878
837
 
879
838
  /* initialize opt[0] */
880
839
  { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
881
840
  opt[0].mlen = 0; /* means is_a_literal */
882
841
  opt[0].litlen = litlen;
883
- 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);
884
848
 
885
849
  /* large match -> immediate encoding */
886
850
  { U32 const maxML = matches[nbMatches-1].len;
@@ -909,7 +873,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
909
873
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
910
874
  U32 const offset = matches[matchNb].off;
911
875
  U32 const end = matches[matchNb].len;
912
- repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
913
876
  for ( ; pos <= end ; pos++ ) {
914
877
  U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
915
878
  U32 const sequencePrice = literalsPrice + matchPrice;
@@ -919,8 +882,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
919
882
  opt[pos].off = offset;
920
883
  opt[pos].litlen = litlen;
921
884
  opt[pos].price = sequencePrice;
922
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
923
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
924
885
  } }
925
886
  last_pos = pos-1;
926
887
  }
@@ -947,7 +908,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
947
908
  opt[cur].off = 0;
948
909
  opt[cur].litlen = litlen;
949
910
  opt[cur].price = price;
950
- memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
951
911
  } else {
952
912
  DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
953
913
  inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
@@ -955,6 +915,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
955
915
  }
956
916
  }
957
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
+
958
933
  /* last match must start at a minimum distance of 8 from oend */
959
934
  if (inr > ilimit) continue;
960
935
 
@@ -970,7 +945,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
970
945
  U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
971
946
  U32 const previousPrice = opt[cur].price;
972
947
  U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
973
- 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);
974
949
  U32 matchNb;
975
950
  if (!nbMatches) {
976
951
  DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -995,7 +970,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
995
970
  /* set prices using matches found at position == cur */
996
971
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
997
972
  U32 const offset = matches[matchNb].off;
998
- repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
999
973
  U32 const lastML = matches[matchNb].len;
1000
974
  U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
1001
975
  U32 mlen;
@@ -1015,8 +989,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1015
989
  opt[pos].off = offset;
1016
990
  opt[pos].litlen = litlen;
1017
991
  opt[pos].price = price;
1018
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
1019
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
1020
992
  } else {
1021
993
  DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
1022
994
  pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
@@ -1032,6 +1004,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1032
1004
  _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1033
1005
  assert(opt[0].mlen == 0);
1034
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
+
1035
1018
  { U32 const storeEnd = cur + 1;
1036
1019
  U32 storeStart = storeEnd;
1037
1020
  U32 seqPos = cur;
@@ -1068,33 +1051,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1068
1051
  continue; /* will finish */
1069
1052
  }
1070
1053
 
1071
- /* repcodes update : like ZSTD_updateRep(), but update in place */
1072
- if (offCode >= ZSTD_REP_NUM) { /* full offset */
1073
- rep[2] = rep[1];
1074
- rep[1] = rep[0];
1075
- rep[0] = offCode - ZSTD_REP_MOVE;
1076
- } else { /* repcode */
1077
- U32 const repCode = offCode + (llen==0);
1078
- if (repCode) { /* note : if repCode==0, no change */
1079
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
1080
- if (repCode >= 2) rep[2] = rep[1];
1081
- rep[1] = rep[0];
1082
- rep[0] = currentOffset;
1083
- } }
1084
-
1085
1054
  assert(anchor + llen <= iend);
1086
1055
  ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
1087
- ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
1056
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
1088
1057
  anchor += advance;
1089
1058
  ip = anchor;
1090
1059
  } }
1091
1060
  ZSTD_setBasePrices(optStatePtr, optLevel);
1092
1061
  }
1093
-
1094
1062
  } /* while (ip < ilimit) */
1095
1063
 
1096
1064
  /* Return the last literals size */
1097
- return iend - anchor;
1065
+ return (size_t)(iend - anchor);
1098
1066
  }
1099
1067
 
1100
1068
 
@@ -1158,7 +1126,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
1158
1126
  ms->window.dictLimit += (U32)srcSize;
1159
1127
  ms->window.lowLimit = ms->window.dictLimit;
1160
1128
  ms->nextToUpdate = ms->window.dictLimit;
1161
- ms->nextToUpdate3 = ms->window.dictLimit;
1162
1129
 
1163
1130
  /* re-inforce weight of collected statistics */
1164
1131
  ZSTD_upscaleStats(&ms->opt);