zstd-ruby 1.4.0.0 → 1.4.9.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +35 -0
  3. data/README.md +2 -2
  4. data/ext/zstdruby/libzstd/Makefile +274 -107
  5. data/ext/zstdruby/libzstd/README.md +75 -16
  6. data/ext/zstdruby/libzstd/common/bitstream.h +59 -51
  7. data/ext/zstdruby/libzstd/common/compiler.h +154 -5
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  9. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  10. data/ext/zstdruby/libzstd/common/debug.h +22 -49
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +201 -75
  12. data/ext/zstdruby/libzstd/common/error_private.c +3 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +7 -3
  14. data/ext/zstdruby/libzstd/common/fse.h +50 -42
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +134 -50
  16. data/ext/zstdruby/libzstd/common/huf.h +41 -38
  17. data/ext/zstdruby/libzstd/common/mem.h +68 -22
  18. data/ext/zstdruby/libzstd/common/pool.c +30 -20
  19. data/ext/zstdruby/libzstd/common/pool.h +3 -3
  20. data/ext/zstdruby/libzstd/common/threading.c +51 -4
  21. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  22. data/ext/zstdruby/libzstd/common/xxhash.c +39 -89
  23. data/ext/zstdruby/libzstd/common/xxhash.h +12 -32
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
  25. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  26. data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
  27. data/ext/zstdruby/libzstd/common/zstd_internal.h +231 -72
  28. data/ext/zstdruby/libzstd/common/zstd_trace.c +42 -0
  29. data/ext/zstdruby/libzstd/common/zstd_trace.h +152 -0
  30. data/ext/zstdruby/libzstd/compress/fse_compress.c +47 -63
  31. data/ext/zstdruby/libzstd/compress/hist.c +41 -63
  32. data/ext/zstdruby/libzstd/compress/hist.h +13 -33
  33. data/ext/zstdruby/libzstd/compress/huf_compress.c +288 -172
  34. data/ext/zstdruby/libzstd/compress/zstd_compress.c +2504 -1626
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +446 -85
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +433 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +849 -0
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  42. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +561 -0
  43. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +82 -60
  44. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  45. data/ext/zstdruby/libzstd/compress/zstd_fast.c +106 -80
  46. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  47. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +411 -105
  48. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +21 -1
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +296 -207
  50. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +14 -3
  51. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
  52. data/ext/zstdruby/libzstd/compress/zstd_opt.c +260 -148
  53. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  54. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +153 -440
  55. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +29 -110
  56. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +356 -238
  57. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +20 -16
  58. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
  59. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +641 -238
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +600 -371
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +8 -5
  62. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +40 -9
  63. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  64. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  65. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  66. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  67. data/ext/zstdruby/libzstd/dictBuilder/cover.c +197 -78
  68. data/ext/zstdruby/libzstd/dictBuilder/cover.h +52 -7
  69. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  70. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +84 -66
  71. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +58 -36
  72. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +60 -31
  73. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  74. data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
  75. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +8 -4
  76. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +115 -111
  77. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
  78. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +28 -14
  79. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
  80. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +28 -14
  81. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
  82. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +36 -19
  83. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
  84. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +122 -107
  85. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +2 -2
  86. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +29 -23
  87. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
  88. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +34 -24
  89. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
  90. data/ext/zstdruby/libzstd/libzstd.pc.in +2 -1
  91. data/ext/zstdruby/libzstd/zstd.h +655 -118
  92. data/lib/zstd-ruby/version.rb +1 -1
  93. data/zstd-ruby.gemspec +1 -1
  94. metadata +20 -10
  95. data/.travis.yml +0 -14
@@ -1,10 +1,11 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, 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
  *
@@ -68,11 +73,17 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
68
73
  *
69
74
  * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.
70
75
  * Avoids emitting matches less than `minMatch` bytes.
71
- * Must be called for data with is not passed to ZSTD_ldm_blockCompress().
76
+ * Must be called for data that is not passed to ZSTD_ldm_blockCompress().
72
77
  */
73
78
  void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize,
74
79
  U32 const minMatch);
75
80
 
81
+ /* ZSTD_ldm_skipRawSeqStoreBytes():
82
+ * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'.
83
+ * Not to be used in conjunction with ZSTD_ldm_skipSequences().
84
+ * Must be called for data with is not passed to ZSTD_ldm_blockCompress().
85
+ */
86
+ void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes);
76
87
 
77
88
  /** ZSTD_ldm_getTableSize() :
78
89
  * Estimate the space needed for long distance matching tables or 0 if LDM is
@@ -0,0 +1,103 @@
1
+ /*
2
+ * Copyright (c) 2016-2021, Yann Collet, 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
+ */
10
+
11
+ #ifndef ZSTD_LDM_GEARTAB_H
12
+ #define ZSTD_LDM_GEARTAB_H
13
+
14
+ static U64 ZSTD_ldm_gearTab[256] = {
15
+ 0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc,
16
+ 0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05,
17
+ 0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e,
18
+ 0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889,
19
+ 0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e,
20
+ 0x37b628620b628, 0x49a8d455d88caf5, 0x8556d711e6958140,
21
+ 0x4f7ae74fc605c1f, 0x829f0c3468bd3a20, 0x4ffdc885c625179e,
22
+ 0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f,
23
+ 0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391,
24
+ 0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210,
25
+ 0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be,
26
+ 0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a,
27
+ 0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b,
28
+ 0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4,
29
+ 0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb,
30
+ 0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312,
31
+ 0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01,
32
+ 0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc,
33
+ 0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967,
34
+ 0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553,
35
+ 0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f,
36
+ 0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2,
37
+ 0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d,
38
+ 0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a,
39
+ 0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74,
40
+ 0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3,
41
+ 0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1,
42
+ 0xff452823dbb010a, 0x9d42ed614f3dd267, 0x5b9313c06257c57b,
43
+ 0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568,
44
+ 0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a,
45
+ 0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1,
46
+ 0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9,
47
+ 0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463,
48
+ 0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba,
49
+ 0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9,
50
+ 0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61,
51
+ 0x24a5483879c453e3, 0x88026889192b4b9, 0x28da96671782dbec,
52
+ 0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6,
53
+ 0xbc135a0a704b70ba, 0x69cd868f7622ada, 0xbc37ba89e0b9c0ab,
54
+ 0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5,
55
+ 0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59,
56
+ 0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7,
57
+ 0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc,
58
+ 0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb,
59
+ 0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be,
60
+ 0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312,
61
+ 0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1,
62
+ 0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc,
63
+ 0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d,
64
+ 0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445,
65
+ 0x820d471e20b348e, 0x1874383cb83d46dc, 0x97edeec7a1efe11c,
66
+ 0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5,
67
+ 0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5,
68
+ 0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28,
69
+ 0xaf846af6ab7d0bf4, 0xe5af208eb666e49, 0x5e6622f73534cd6a,
70
+ 0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9,
71
+ 0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15,
72
+ 0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef,
73
+ 0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2,
74
+ 0x9f90e4c5fd508d8, 0xa34e5956fbaf3385, 0x2e2f8e151d3ef375,
75
+ 0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3,
76
+ 0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595,
77
+ 0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389,
78
+ 0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4,
79
+ 0x4228e364c5b5ed7, 0x9d7a3edf0da43911, 0x8edcfeda24686756,
80
+ 0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc,
81
+ 0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45,
82
+ 0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea,
83
+ 0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f,
84
+ 0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc,
85
+ 0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c,
86
+ 0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a,
87
+ 0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17,
88
+ 0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3,
89
+ 0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4,
90
+ 0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91,
91
+ 0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40,
92
+ 0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741,
93
+ 0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f,
94
+ 0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4,
95
+ 0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad,
96
+ 0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047,
97
+ 0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2,
98
+ 0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e,
99
+ 0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b,
100
+ 0x2b4da14f2613d8f4
101
+ };
102
+
103
+ #endif /* ZSTD_LDM_GEARTAB_H */
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, 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
 
@@ -417,32 +386,32 @@ static U32 ZSTD_insertBt1(
417
386
  const BYTE* const dictEnd = dictBase + dictLimit;
418
387
  const BYTE* const prefixStart = base + dictLimit;
419
388
  const BYTE* match;
420
- const U32 current = (U32)(ip-base);
421
- const U32 btLow = btMask >= current ? 0 : current - btMask;
422
- U32* smallerPtr = bt + 2*(current&btMask);
389
+ const U32 curr = (U32)(ip-base);
390
+ const U32 btLow = btMask >= curr ? 0 : curr - btMask;
391
+ U32* smallerPtr = bt + 2*(curr&btMask);
423
392
  U32* largerPtr = smallerPtr + 1;
424
393
  U32 dummy32; /* to be nullified at the end */
425
394
  U32 const windowLow = ms->window.lowLimit;
426
- U32 matchEndIdx = current+8+1;
395
+ U32 matchEndIdx = curr+8+1;
427
396
  size_t bestLength = 8;
428
397
  U32 nbCompares = 1U << cParams->searchLog;
429
398
  #ifdef ZSTD_C_PREDICT
430
- U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
431
- U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
399
+ U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0);
400
+ U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1);
432
401
  predictedSmall += (predictedSmall>0);
433
402
  predictedLarge += (predictedLarge>0);
434
403
  #endif /* ZSTD_C_PREDICT */
435
404
 
436
- DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current);
405
+ DEBUGLOG(8, "ZSTD_insertBt1 (%u)", curr);
437
406
 
438
407
  assert(ip <= iend-8); /* required for h calculation */
439
- hashTable[h] = current; /* Update Hash Table */
408
+ hashTable[h] = curr; /* Update Hash Table */
440
409
 
441
410
  assert(windowLow > 0);
442
411
  while (nbCompares-- && (matchIndex >= windowLow)) {
443
412
  U32* const nextPtr = bt + 2*(matchIndex & btMask);
444
413
  size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
445
- assert(matchIndex < current);
414
+ assert(matchIndex < curr);
446
415
 
447
416
  #ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
448
417
  const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
@@ -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 > curr + 8);
478
+ return MAX(positions, matchEndIdx - (curr + 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,18 +507,19 @@ 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
  {
542
519
  const ZSTD_compressionParameters* const cParams = &ms->cParams;
543
520
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
544
521
  const BYTE* const base = ms->window.base;
545
- U32 const current = (U32)(ip-base);
522
+ U32 const curr = (U32)(ip-base);
546
523
  U32 const hashLog = cParams->hashLog;
547
524
  U32 const minMatch = (mls==3) ? 3 : 4;
548
525
  U32* const hashTable = ms->hashTable;
@@ -556,12 +533,12 @@ 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 >= curr) ? 0 : curr - btMask;
537
+ U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);
561
538
  U32 const matchLow = windowLow ? windowLow : 1;
562
- U32* smallerPtr = bt + 2*(current&btMask);
563
- U32* largerPtr = bt + 2*(current&btMask) + 1;
564
- U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */
539
+ U32* smallerPtr = bt + 2*(curr&btMask);
540
+ U32* largerPtr = bt + 2*(curr&btMask) + 1;
541
+ U32 matchEndIdx = curr+8+1; /* farthest referenced position of any match => detects repetitive patterns */
565
542
  U32 dummy32; /* to be nullified at the end */
566
543
  U32 mnum = 0;
567
544
  U32 nbCompares = 1U << cParams->searchLog;
@@ -580,7 +557,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
580
557
  U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit;
581
558
 
582
559
  size_t bestLength = lengthToBeat-1;
583
- DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current);
560
+ DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", curr);
584
561
 
585
562
  /* check repCode */
586
563
  assert(ll0 <= 1); /* necessarily 1 or 0 */
@@ -588,26 +565,29 @@ U32 ZSTD_insertBtAndGetAllMatches (
588
565
  U32 repCode;
589
566
  for (repCode = ll0; repCode < lastR; repCode++) {
590
567
  U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
591
- U32 const repIndex = current - repOffset;
568
+ U32 const repIndex = curr - repOffset;
592
569
  U32 repLen = 0;
593
- assert(current >= dictLimit);
594
- 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)) {
570
+ assert(curr >= dictLimit);
571
+ if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) { /* equivalent to `curr > repIndex >= dictLimit` */
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
- } else { /* repIndex < dictLimit || repIndex >= current */
578
+ } else { /* repIndex < dictLimit || repIndex >= curr */
599
579
  const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ?
600
580
  dmsBase + repIndex - dmsIndexDelta :
601
581
  dictBase + repIndex;
602
- assert(current >= windowLow);
582
+ assert(curr >= windowLow);
603
583
  if ( dictMode == ZSTD_extDict
604
- && ( ((repOffset-1) /*intentional overflow*/ < current - windowLow) /* equivalent to `current > repIndex >= windowLow` */
584
+ && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow) /* equivalent to `curr > repIndex >= windowLow` */
605
585
  & (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */)
606
586
  && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
607
587
  repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch;
608
588
  }
609
589
  if (dictMode == ZSTD_dictMatchState
610
- && ( ((repOffset-1) /*intentional overflow*/ < current - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `current > repIndex >= dmsLowLimit` */
590
+ && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `curr > repIndex >= dmsLowLimit` */
611
591
  & ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */
612
592
  && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
613
593
  repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch;
@@ -627,9 +607,9 @@ 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
- & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
612
+ & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
633
613
  size_t mlen;
634
614
  if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) {
635
615
  const BYTE* const match = base + matchIndex3;
@@ -644,48 +624,48 @@ U32 ZSTD_insertBtAndGetAllMatches (
644
624
  DEBUGLOG(8, "found small match with hlog3, of length %u",
645
625
  (U32)mlen);
646
626
  bestLength = mlen;
647
- assert(current > matchIndex3);
627
+ assert(curr > matchIndex3);
648
628
  assert(mnum==0); /* no prior solution */
649
- matches[0].off = (current - matchIndex3) + ZSTD_REP_MOVE;
629
+ matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE;
650
630
  matches[0].len = (U32)mlen;
651
631
  mnum = 1;
652
632
  if ( (mlen > sufficient_len) |
653
633
  (ip+mlen == iLimit) ) { /* best possible length */
654
- ms->nextToUpdate = current+1; /* skip insertion */
634
+ ms->nextToUpdate = curr+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
 
662
- hashTable[h] = current; /* Update Hash Table */
640
+ hashTable[h] = curr; /* Update Hash Table */
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;
668
- assert(current > matchIndex);
645
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
646
+ assert(curr > 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) {
682
662
  DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)",
683
- (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE);
663
+ (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
684
664
  assert(matchEndIdx > matchIndex);
685
665
  if (matchLength > matchEndIdx - matchIndex)
686
666
  matchEndIdx = matchIndex + (U32)matchLength;
687
667
  bestLength = matchLength;
688
- matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE;
668
+ matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
689
669
  matches[mnum].len = (U32)matchLength;
690
670
  mnum++;
691
671
  if ( (matchLength > ZSTD_OPT_NUM)
@@ -728,11 +708,11 @@ U32 ZSTD_insertBtAndGetAllMatches (
728
708
  if (matchLength > bestLength) {
729
709
  matchIndex = dictMatchIndex + dmsIndexDelta;
730
710
  DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)",
731
- (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE);
711
+ (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
732
712
  if (matchLength > matchEndIdx - matchIndex)
733
713
  matchEndIdx = matchIndex + (U32)matchLength;
734
714
  bestLength = matchLength;
735
- matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE;
715
+ matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
736
716
  matches[mnum].len = (U32)matchLength;
737
717
  mnum++;
738
718
  if ( (matchLength > ZSTD_OPT_NUM)
@@ -753,17 +733,20 @@ U32 ZSTD_insertBtAndGetAllMatches (
753
733
  }
754
734
  }
755
735
 
756
- assert(matchEndIdx > current+8);
736
+ assert(matchEndIdx > curr+8);
757
737
  ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
758
738
  return mnum;
759
739
  }
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,44 +755,154 @@ 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
 
767
+ /*************************
768
+ * LDM helper functions *
769
+ *************************/
784
770
 
785
- /*-*******************************
786
- * Optimal parser
787
- *********************************/
788
- typedef struct repcodes_s {
789
- U32 rep[3];
790
- } repcodes_t;
771
+ /* Struct containing info needed to make decision about ldm inclusion */
772
+ typedef struct {
773
+ rawSeqStore_t seqStore; /* External match candidates store for this block */
774
+ U32 startPosInBlock; /* Start position of the current match candidate */
775
+ U32 endPosInBlock; /* End position of the current match candidate */
776
+ U32 offset; /* Offset of the match candidate */
777
+ } ZSTD_optLdm_t;
791
778
 
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));
779
+ /* ZSTD_optLdm_skipRawSeqStoreBytes():
780
+ * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
781
+ */
782
+ static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
783
+ U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
784
+ while (currPos && rawSeqStore->pos < rawSeqStore->size) {
785
+ rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
786
+ if (currPos >= currSeq.litLength + currSeq.matchLength) {
787
+ currPos -= currSeq.litLength + currSeq.matchLength;
788
+ rawSeqStore->pos++;
789
+ } else {
790
+ rawSeqStore->posInSequence = currPos;
791
+ break;
808
792
  }
809
793
  }
810
- return newReps;
794
+ if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
795
+ rawSeqStore->posInSequence = 0;
796
+ }
797
+ }
798
+
799
+ /* ZSTD_opt_getNextMatchAndUpdateSeqStore():
800
+ * Calculates the beginning and end of the next match in the current block.
801
+ * Updates 'pos' and 'posInSequence' of the ldmSeqStore.
802
+ */
803
+ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
804
+ U32 blockBytesRemaining) {
805
+ rawSeq currSeq;
806
+ U32 currBlockEndPos;
807
+ U32 literalsBytesRemaining;
808
+ U32 matchBytesRemaining;
809
+
810
+ /* Setting match end position to MAX to ensure we never use an LDM during this block */
811
+ if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
812
+ optLdm->startPosInBlock = UINT_MAX;
813
+ optLdm->endPosInBlock = UINT_MAX;
814
+ return;
815
+ }
816
+ /* Calculate appropriate bytes left in matchLength and litLength after adjusting
817
+ based on ldmSeqStore->posInSequence */
818
+ currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];
819
+ assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);
820
+ currBlockEndPos = currPosInBlock + blockBytesRemaining;
821
+ literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ?
822
+ currSeq.litLength - (U32)optLdm->seqStore.posInSequence :
823
+ 0;
824
+ matchBytesRemaining = (literalsBytesRemaining == 0) ?
825
+ currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) :
826
+ currSeq.matchLength;
827
+
828
+ /* If there are more literal bytes than bytes remaining in block, no ldm is possible */
829
+ if (literalsBytesRemaining >= blockBytesRemaining) {
830
+ optLdm->startPosInBlock = UINT_MAX;
831
+ optLdm->endPosInBlock = UINT_MAX;
832
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining);
833
+ return;
834
+ }
835
+
836
+ /* Matches may be < MINMATCH by this process. In that case, we will reject them
837
+ when we are deciding whether or not to add the ldm */
838
+ optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining;
839
+ optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining;
840
+ optLdm->offset = currSeq.offset;
841
+
842
+ if (optLdm->endPosInBlock > currBlockEndPos) {
843
+ /* Match ends after the block ends, we can't use the whole match */
844
+ optLdm->endPosInBlock = currBlockEndPos;
845
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock);
846
+ } else {
847
+ /* Consume nb of bytes equal to size of sequence left */
848
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining);
849
+ }
850
+ }
851
+
852
+ /* ZSTD_optLdm_maybeAddMatch():
853
+ * Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
854
+ * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
855
+ */
856
+ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
857
+ ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
858
+ U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
859
+ /* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
860
+ U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
861
+ U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE;
862
+
863
+ /* Ensure that current block position is not outside of the match */
864
+ if (currPosInBlock < optLdm->startPosInBlock
865
+ || currPosInBlock >= optLdm->endPosInBlock
866
+ || candidateMatchLength < MINMATCH) {
867
+ return;
868
+ }
869
+
870
+ if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {
871
+ DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
872
+ candidateOffCode, candidateMatchLength, currPosInBlock);
873
+ matches[*nbMatches].len = candidateMatchLength;
874
+ matches[*nbMatches].off = candidateOffCode;
875
+ (*nbMatches)++;
876
+ }
811
877
  }
812
878
 
879
+ /* ZSTD_optLdm_processMatchCandidate():
880
+ * Wrapper function to update ldm seq store and call ldm functions as necessary.
881
+ */
882
+ static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
883
+ U32 currPosInBlock, U32 remainingBytes) {
884
+ if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
885
+ return;
886
+ }
887
+
888
+ if (currPosInBlock >= optLdm->endPosInBlock) {
889
+ if (currPosInBlock > optLdm->endPosInBlock) {
890
+ /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily
891
+ * at the end of a match from the ldm seq store, and will often be some bytes
892
+ * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
893
+ */
894
+ U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
895
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);
896
+ }
897
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
898
+ }
899
+ ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock);
900
+ }
901
+
902
+ /*-*******************************
903
+ * Optimal parser
904
+ *********************************/
905
+
813
906
 
814
907
  static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
815
908
  {
@@ -825,7 +918,7 @@ listStats(const U32* table, int lastEltID)
825
918
  int enb;
826
919
  for (enb=0; enb < nbElts; enb++) {
827
920
  (void)table;
828
- //RAWLOG(2, "%3i:%3i, ", enb, table[enb]);
921
+ /* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
829
922
  RAWLOG(2, "%4i,", table[enb]);
830
923
  }
831
924
  RAWLOG(2, " \n");
@@ -853,16 +946,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
853
946
 
854
947
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
855
948
  U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
949
+ U32 nextToUpdate3 = ms->nextToUpdate;
856
950
 
857
951
  ZSTD_optimal_t* const opt = optStatePtr->priceTable;
858
952
  ZSTD_match_t* const matches = optStatePtr->matchTable;
859
953
  ZSTD_optimal_t lastSequence;
954
+ ZSTD_optLdm_t optLdm;
955
+
956
+ optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;
957
+ optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
958
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
860
959
 
861
960
  /* init */
862
961
  DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
863
962
  (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
864
963
  assert(optLevel <= 2);
865
- ms->nextToUpdate3 = ms->nextToUpdate;
866
964
  ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
867
965
  ip += (ip==prefixStart);
868
966
 
@@ -873,14 +971,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
873
971
  /* find first match */
874
972
  { U32 const litlen = (U32)(ip - anchor);
875
973
  U32 const ll0 = !litlen;
876
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
974
+ U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
975
+ ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
976
+ (U32)(ip-istart), (U32)(iend - ip));
877
977
  if (!nbMatches) { ip++; continue; }
878
978
 
879
979
  /* initialize opt[0] */
880
980
  { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
881
981
  opt[0].mlen = 0; /* means is_a_literal */
882
982
  opt[0].litlen = litlen;
883
- opt[0].price = ZSTD_literalsContribution(anchor, litlen, optStatePtr, optLevel);
983
+ /* We don't need to include the actual price of the literals because
984
+ * it is static for the duration of the forward pass, and is included
985
+ * in every price. We include the literal length to avoid negative
986
+ * prices when we subtract the previous literal length.
987
+ */
988
+ opt[0].price = ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
884
989
 
885
990
  /* large match -> immediate encoding */
886
991
  { U32 const maxML = matches[nbMatches-1].len;
@@ -909,7 +1014,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
909
1014
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
910
1015
  U32 const offset = matches[matchNb].off;
911
1016
  U32 const end = matches[matchNb].len;
912
- repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
913
1017
  for ( ; pos <= end ; pos++ ) {
914
1018
  U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
915
1019
  U32 const sequencePrice = literalsPrice + matchPrice;
@@ -919,8 +1023,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
919
1023
  opt[pos].off = offset;
920
1024
  opt[pos].litlen = litlen;
921
1025
  opt[pos].price = sequencePrice;
922
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
923
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
924
1026
  } }
925
1027
  last_pos = pos-1;
926
1028
  }
@@ -947,7 +1049,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
947
1049
  opt[cur].off = 0;
948
1050
  opt[cur].litlen = litlen;
949
1051
  opt[cur].price = price;
950
- memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
951
1052
  } else {
952
1053
  DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
953
1054
  inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
@@ -955,6 +1056,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
955
1056
  }
956
1057
  }
957
1058
 
1059
+ /* Set the repcodes of the current position. We must do it here
1060
+ * because we rely on the repcodes of the 2nd to last sequence being
1061
+ * correct to set the next chunks repcodes during the backward
1062
+ * traversal.
1063
+ */
1064
+ ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t));
1065
+ assert(cur >= opt[cur].mlen);
1066
+ if (opt[cur].mlen != 0) {
1067
+ U32 const prev = cur - opt[cur].mlen;
1068
+ repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
1069
+ ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
1070
+ } else {
1071
+ ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
1072
+ }
1073
+
958
1074
  /* last match must start at a minimum distance of 8 from oend */
959
1075
  if (inr > ilimit) continue;
960
1076
 
@@ -970,8 +1086,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
970
1086
  U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
971
1087
  U32 const previousPrice = opt[cur].price;
972
1088
  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);
1089
+ U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
974
1090
  U32 matchNb;
1091
+
1092
+ ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
1093
+ (U32)(inr-istart), (U32)(iend-inr));
1094
+
975
1095
  if (!nbMatches) {
976
1096
  DEBUGLOG(7, "rPos:%u : no match found", cur);
977
1097
  continue;
@@ -995,7 +1115,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
995
1115
  /* set prices using matches found at position == cur */
996
1116
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
997
1117
  U32 const offset = matches[matchNb].off;
998
- repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
999
1118
  U32 const lastML = matches[matchNb].len;
1000
1119
  U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
1001
1120
  U32 mlen;
@@ -1015,8 +1134,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1015
1134
  opt[pos].off = offset;
1016
1135
  opt[pos].litlen = litlen;
1017
1136
  opt[pos].price = price;
1018
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
1019
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
1020
1137
  } else {
1021
1138
  DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
1022
1139
  pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
@@ -1032,6 +1149,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1032
1149
  _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1033
1150
  assert(opt[0].mlen == 0);
1034
1151
 
1152
+ /* Set the next chunk's repcodes based on the repcodes of the beginning
1153
+ * of the last match, and the last sequence. This avoids us having to
1154
+ * update them while traversing the sequences.
1155
+ */
1156
+ if (lastSequence.mlen != 0) {
1157
+ repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
1158
+ ZSTD_memcpy(rep, &reps, sizeof(reps));
1159
+ } else {
1160
+ ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
1161
+ }
1162
+
1035
1163
  { U32 const storeEnd = cur + 1;
1036
1164
  U32 storeStart = storeEnd;
1037
1165
  U32 seqPos = cur;
@@ -1068,33 +1196,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1068
1196
  continue; /* will finish */
1069
1197
  }
1070
1198
 
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
1199
  assert(anchor + llen <= iend);
1086
1200
  ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
1087
- ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
1201
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
1088
1202
  anchor += advance;
1089
1203
  ip = anchor;
1090
1204
  } }
1091
1205
  ZSTD_setBasePrices(optStatePtr, optLevel);
1092
1206
  }
1093
-
1094
1207
  } /* while (ip < ilimit) */
1095
1208
 
1096
1209
  /* Return the last literals size */
1097
- return iend - anchor;
1210
+ return (size_t)(iend - anchor);
1098
1211
  }
1099
1212
 
1100
1213
 
@@ -1142,7 +1255,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
1142
1255
  const void* src, size_t srcSize)
1143
1256
  {
1144
1257
  U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
1145
- memcpy(tmpRep, rep, sizeof(tmpRep));
1258
+ ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));
1146
1259
 
1147
1260
  DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize);
1148
1261
  assert(ms->opt.litLengthSum == 0); /* first block */
@@ -1158,7 +1271,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
1158
1271
  ms->window.dictLimit += (U32)srcSize;
1159
1272
  ms->window.lowLimit = ms->window.dictLimit;
1160
1273
  ms->nextToUpdate = ms->window.dictLimit;
1161
- ms->nextToUpdate3 = ms->window.dictLimit;
1162
1274
 
1163
1275
  /* re-inforce weight of collected statistics */
1164
1276
  ZSTD_upscaleStats(&ms->opt);
@@ -1176,7 +1288,7 @@ size_t ZSTD_compressBlock_btultra2(
1176
1288
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1177
1289
  const void* src, size_t srcSize)
1178
1290
  {
1179
- U32 const current = (U32)((const BYTE*)src - ms->window.base);
1291
+ U32 const curr = (U32)((const BYTE*)src - ms->window.base);
1180
1292
  DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize);
1181
1293
 
1182
1294
  /* 2-pass strategy:
@@ -1191,7 +1303,7 @@ size_t ZSTD_compressBlock_btultra2(
1191
1303
  if ( (ms->opt.litLengthSum==0) /* first block */
1192
1304
  && (seqStore->sequences == seqStore->sequencesStart) /* no ldm */
1193
1305
  && (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */
1194
- && (current == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
1306
+ && (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
1195
1307
  && (srcSize > ZSTD_PREDEF_THRESHOLD)
1196
1308
  ) {
1197
1309
  ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);