extzstd 0.3.2 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/contrib/zstd/CHANGELOG +225 -1
  4. data/contrib/zstd/CONTRIBUTING.md +158 -75
  5. data/contrib/zstd/LICENSE +4 -4
  6. data/contrib/zstd/Makefile +106 -69
  7. data/contrib/zstd/Package.swift +36 -0
  8. data/contrib/zstd/README.md +64 -36
  9. data/contrib/zstd/SECURITY.md +15 -0
  10. data/contrib/zstd/TESTING.md +2 -3
  11. data/contrib/zstd/lib/BUCK +5 -7
  12. data/contrib/zstd/lib/Makefile +117 -199
  13. data/contrib/zstd/lib/README.md +37 -7
  14. data/contrib/zstd/lib/common/allocations.h +55 -0
  15. data/contrib/zstd/lib/common/bits.h +200 -0
  16. data/contrib/zstd/lib/common/bitstream.h +80 -86
  17. data/contrib/zstd/lib/common/compiler.h +225 -63
  18. data/contrib/zstd/lib/common/cpu.h +37 -1
  19. data/contrib/zstd/lib/common/debug.c +7 -1
  20. data/contrib/zstd/lib/common/debug.h +21 -12
  21. data/contrib/zstd/lib/common/entropy_common.c +15 -37
  22. data/contrib/zstd/lib/common/error_private.c +9 -2
  23. data/contrib/zstd/lib/common/error_private.h +93 -5
  24. data/contrib/zstd/lib/common/fse.h +12 -87
  25. data/contrib/zstd/lib/common/fse_decompress.c +37 -117
  26. data/contrib/zstd/lib/common/huf.h +97 -172
  27. data/contrib/zstd/lib/common/mem.h +58 -58
  28. data/contrib/zstd/lib/common/pool.c +38 -17
  29. data/contrib/zstd/lib/common/pool.h +10 -4
  30. data/contrib/zstd/lib/common/portability_macros.h +158 -0
  31. data/contrib/zstd/lib/common/threading.c +74 -14
  32. data/contrib/zstd/lib/common/threading.h +5 -10
  33. data/contrib/zstd/lib/common/xxhash.c +6 -814
  34. data/contrib/zstd/lib/common/xxhash.h +6930 -195
  35. data/contrib/zstd/lib/common/zstd_common.c +1 -36
  36. data/contrib/zstd/lib/common/zstd_deps.h +1 -1
  37. data/contrib/zstd/lib/common/zstd_internal.h +68 -154
  38. data/contrib/zstd/lib/common/zstd_trace.h +163 -0
  39. data/contrib/zstd/lib/compress/clevels.h +134 -0
  40. data/contrib/zstd/lib/compress/fse_compress.c +75 -155
  41. data/contrib/zstd/lib/compress/hist.c +1 -1
  42. data/contrib/zstd/lib/compress/hist.h +1 -1
  43. data/contrib/zstd/lib/compress/huf_compress.c +810 -259
  44. data/contrib/zstd/lib/compress/zstd_compress.c +2864 -919
  45. data/contrib/zstd/lib/compress/zstd_compress_internal.h +523 -192
  46. data/contrib/zstd/lib/compress/zstd_compress_literals.c +117 -40
  47. data/contrib/zstd/lib/compress/zstd_compress_literals.h +16 -6
  48. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +28 -19
  49. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +1 -1
  50. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +251 -412
  51. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +1 -1
  52. data/contrib/zstd/lib/compress/zstd_cwksp.h +284 -97
  53. data/contrib/zstd/lib/compress/zstd_double_fast.c +382 -133
  54. data/contrib/zstd/lib/compress/zstd_double_fast.h +14 -2
  55. data/contrib/zstd/lib/compress/zstd_fast.c +732 -260
  56. data/contrib/zstd/lib/compress/zstd_fast.h +3 -2
  57. data/contrib/zstd/lib/compress/zstd_lazy.c +1177 -390
  58. data/contrib/zstd/lib/compress/zstd_lazy.h +129 -14
  59. data/contrib/zstd/lib/compress/zstd_ldm.c +280 -210
  60. data/contrib/zstd/lib/compress/zstd_ldm.h +3 -2
  61. data/contrib/zstd/lib/compress/zstd_ldm_geartab.h +106 -0
  62. data/contrib/zstd/lib/compress/zstd_opt.c +516 -285
  63. data/contrib/zstd/lib/compress/zstd_opt.h +32 -8
  64. data/contrib/zstd/lib/compress/zstdmt_compress.c +202 -131
  65. data/contrib/zstd/lib/compress/zstdmt_compress.h +9 -6
  66. data/contrib/zstd/lib/decompress/huf_decompress.c +1149 -555
  67. data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +595 -0
  68. data/contrib/zstd/lib/decompress/zstd_ddict.c +4 -4
  69. data/contrib/zstd/lib/decompress/zstd_ddict.h +1 -1
  70. data/contrib/zstd/lib/decompress/zstd_decompress.c +583 -106
  71. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1054 -379
  72. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +14 -3
  73. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +56 -6
  74. data/contrib/zstd/lib/deprecated/zbuff.h +1 -1
  75. data/contrib/zstd/lib/deprecated/zbuff_common.c +1 -1
  76. data/contrib/zstd/lib/deprecated/zbuff_compress.c +24 -4
  77. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +3 -1
  78. data/contrib/zstd/lib/dictBuilder/cover.c +60 -44
  79. data/contrib/zstd/lib/dictBuilder/cover.h +6 -11
  80. data/contrib/zstd/lib/dictBuilder/divsufsort.c +1 -1
  81. data/contrib/zstd/lib/dictBuilder/fastcover.c +26 -18
  82. data/contrib/zstd/lib/dictBuilder/zdict.c +100 -101
  83. data/contrib/zstd/lib/legacy/zstd_legacy.h +38 -1
  84. data/contrib/zstd/lib/legacy/zstd_v01.c +18 -53
  85. data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
  86. data/contrib/zstd/lib/legacy/zstd_v02.c +28 -85
  87. data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
  88. data/contrib/zstd/lib/legacy/zstd_v03.c +29 -88
  89. data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
  90. data/contrib/zstd/lib/legacy/zstd_v04.c +27 -80
  91. data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
  92. data/contrib/zstd/lib/legacy/zstd_v05.c +36 -85
  93. data/contrib/zstd/lib/legacy/zstd_v05.h +1 -1
  94. data/contrib/zstd/lib/legacy/zstd_v06.c +44 -96
  95. data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
  96. data/contrib/zstd/lib/legacy/zstd_v07.c +37 -92
  97. data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
  98. data/contrib/zstd/lib/libzstd.mk +237 -0
  99. data/contrib/zstd/lib/libzstd.pc.in +4 -3
  100. data/contrib/zstd/lib/module.modulemap +35 -0
  101. data/contrib/zstd/lib/{dictBuilder/zdict.h → zdict.h} +202 -33
  102. data/contrib/zstd/lib/zstd.h +1030 -332
  103. data/contrib/zstd/lib/{common/zstd_errors.h → zstd_errors.h} +27 -8
  104. data/ext/extconf.rb +26 -7
  105. data/ext/extzstd.c +51 -24
  106. data/ext/extzstd.h +33 -6
  107. data/ext/extzstd_stream.c +74 -31
  108. data/ext/libzstd_conf.h +0 -1
  109. data/ext/zstd_decompress_asm.S +1 -0
  110. metadata +17 -7
  111. data/contrib/zstd/appveyor.yml +0 -292
  112. data/ext/depend +0 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -15,288 +15,10 @@
15
15
 
16
16
  #include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */
17
17
  #include "hist.h" /* HIST_countFast_wksp */
18
- #include "zstd_compress_internal.h"
18
+ #include "zstd_compress_internal.h" /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */
19
19
  #include "zstd_compress_sequences.h"
20
20
  #include "zstd_compress_literals.h"
21
21
 
22
- /*-*************************************
23
- * Superblock entropy buffer structs
24
- ***************************************/
25
- /** ZSTD_hufCTablesMetadata_t :
26
- * Stores Literals Block Type for a super-block in hType, and
27
- * huffman tree description in hufDesBuffer.
28
- * hufDesSize refers to the size of huffman tree description in bytes.
29
- * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
30
- typedef struct {
31
- symbolEncodingType_e hType;
32
- BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
33
- size_t hufDesSize;
34
- } ZSTD_hufCTablesMetadata_t;
35
-
36
- /** ZSTD_fseCTablesMetadata_t :
37
- * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
38
- * fse tables in fseTablesBuffer.
39
- * fseTablesSize refers to the size of fse tables in bytes.
40
- * This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */
41
- typedef struct {
42
- symbolEncodingType_e llType;
43
- symbolEncodingType_e ofType;
44
- symbolEncodingType_e mlType;
45
- BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
46
- size_t fseTablesSize;
47
- size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
48
- } ZSTD_fseCTablesMetadata_t;
49
-
50
- typedef struct {
51
- ZSTD_hufCTablesMetadata_t hufMetadata;
52
- ZSTD_fseCTablesMetadata_t fseMetadata;
53
- } ZSTD_entropyCTablesMetadata_t;
54
-
55
-
56
- /** ZSTD_buildSuperBlockEntropy_literal() :
57
- * Builds entropy for the super-block literals.
58
- * Stores literals block type (raw, rle, compressed, repeat) and
59
- * huffman description table to hufMetadata.
60
- * @return : size of huffman description table or error code */
61
- static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize,
62
- const ZSTD_hufCTables_t* prevHuf,
63
- ZSTD_hufCTables_t* nextHuf,
64
- ZSTD_hufCTablesMetadata_t* hufMetadata,
65
- const int disableLiteralsCompression,
66
- void* workspace, size_t wkspSize)
67
- {
68
- BYTE* const wkspStart = (BYTE*)workspace;
69
- BYTE* const wkspEnd = wkspStart + wkspSize;
70
- BYTE* const countWkspStart = wkspStart;
71
- unsigned* const countWksp = (unsigned*)workspace;
72
- const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);
73
- BYTE* const nodeWksp = countWkspStart + countWkspSize;
74
- const size_t nodeWkspSize = wkspEnd-nodeWksp;
75
- unsigned maxSymbolValue = 255;
76
- unsigned huffLog = HUF_TABLELOG_DEFAULT;
77
- HUF_repeat repeat = prevHuf->repeatMode;
78
-
79
- DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
80
-
81
- /* Prepare nextEntropy assuming reusing the existing table */
82
- ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
83
-
84
- if (disableLiteralsCompression) {
85
- DEBUGLOG(5, "set_basic - disabled");
86
- hufMetadata->hType = set_basic;
87
- return 0;
88
- }
89
-
90
- /* small ? don't even attempt compression (speed opt) */
91
- # define COMPRESS_LITERALS_SIZE_MIN 63
92
- { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
93
- if (srcSize <= minLitSize) {
94
- DEBUGLOG(5, "set_basic - too small");
95
- hufMetadata->hType = set_basic;
96
- return 0;
97
- }
98
- }
99
-
100
- /* Scan input and build symbol stats */
101
- { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize);
102
- FORWARD_IF_ERROR(largest, "HIST_count_wksp failed");
103
- if (largest == srcSize) {
104
- DEBUGLOG(5, "set_rle");
105
- hufMetadata->hType = set_rle;
106
- return 0;
107
- }
108
- if (largest <= (srcSize >> 7)+4) {
109
- DEBUGLOG(5, "set_basic - no gain");
110
- hufMetadata->hType = set_basic;
111
- return 0;
112
- }
113
- }
114
-
115
- /* Validate the previous Huffman table */
116
- if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {
117
- repeat = HUF_repeat_none;
118
- }
119
-
120
- /* Build Huffman Tree */
121
- ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
122
- huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
123
- { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
124
- maxSymbolValue, huffLog,
125
- nodeWksp, nodeWkspSize);
126
- FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp");
127
- huffLog = (U32)maxBits;
128
- { /* Build and write the CTable */
129
- size_t const newCSize = HUF_estimateCompressedSize(
130
- (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
131
- size_t const hSize = HUF_writeCTable(
132
- hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
133
- (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog);
134
- /* Check against repeating the previous CTable */
135
- if (repeat != HUF_repeat_none) {
136
- size_t const oldCSize = HUF_estimateCompressedSize(
137
- (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
138
- if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
139
- DEBUGLOG(5, "set_repeat - smaller");
140
- ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
141
- hufMetadata->hType = set_repeat;
142
- return 0;
143
- }
144
- }
145
- if (newCSize + hSize >= srcSize) {
146
- DEBUGLOG(5, "set_basic - no gains");
147
- ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
148
- hufMetadata->hType = set_basic;
149
- return 0;
150
- }
151
- DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize);
152
- hufMetadata->hType = set_compressed;
153
- nextHuf->repeatMode = HUF_repeat_check;
154
- return hSize;
155
- }
156
- }
157
- }
158
-
159
- /** ZSTD_buildSuperBlockEntropy_sequences() :
160
- * Builds entropy for the super-block sequences.
161
- * Stores symbol compression modes and fse table to fseMetadata.
162
- * @return : size of fse tables or error code */
163
- static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
164
- const ZSTD_fseCTables_t* prevEntropy,
165
- ZSTD_fseCTables_t* nextEntropy,
166
- const ZSTD_CCtx_params* cctxParams,
167
- ZSTD_fseCTablesMetadata_t* fseMetadata,
168
- void* workspace, size_t wkspSize)
169
- {
170
- BYTE* const wkspStart = (BYTE*)workspace;
171
- BYTE* const wkspEnd = wkspStart + wkspSize;
172
- BYTE* const countWkspStart = wkspStart;
173
- unsigned* const countWksp = (unsigned*)workspace;
174
- const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned);
175
- BYTE* const cTableWksp = countWkspStart + countWkspSize;
176
- const size_t cTableWkspSize = wkspEnd-cTableWksp;
177
- ZSTD_strategy const strategy = cctxParams->cParams.strategy;
178
- FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
179
- FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
180
- FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
181
- const BYTE* const ofCodeTable = seqStorePtr->ofCode;
182
- const BYTE* const llCodeTable = seqStorePtr->llCode;
183
- const BYTE* const mlCodeTable = seqStorePtr->mlCode;
184
- size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
185
- BYTE* const ostart = fseMetadata->fseTablesBuffer;
186
- BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
187
- BYTE* op = ostart;
188
-
189
- assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
190
- DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
191
- ZSTD_memset(workspace, 0, wkspSize);
192
-
193
- fseMetadata->lastCountSize = 0;
194
- /* convert length/distances into codes */
195
- ZSTD_seqToCodes(seqStorePtr);
196
- /* build CTable for Literal Lengths */
197
- { U32 LLtype;
198
- unsigned max = MaxLL;
199
- size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
200
- DEBUGLOG(5, "Building LL table");
201
- nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
202
- LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
203
- countWksp, max, mostFrequent, nbSeq,
204
- LLFSELog, prevEntropy->litlengthCTable,
205
- LL_defaultNorm, LL_defaultNormLog,
206
- ZSTD_defaultAllowed, strategy);
207
- assert(set_basic < set_compressed && set_rle < set_compressed);
208
- assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
209
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
210
- countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
211
- prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
212
- cTableWksp, cTableWkspSize);
213
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
214
- if (LLtype == set_compressed)
215
- fseMetadata->lastCountSize = countSize;
216
- op += countSize;
217
- fseMetadata->llType = (symbolEncodingType_e) LLtype;
218
- } }
219
- /* build CTable for Offsets */
220
- { U32 Offtype;
221
- unsigned max = MaxOff;
222
- size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
223
- /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
224
- ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
225
- DEBUGLOG(5, "Building OF table");
226
- nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
227
- Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
228
- countWksp, max, mostFrequent, nbSeq,
229
- OffFSELog, prevEntropy->offcodeCTable,
230
- OF_defaultNorm, OF_defaultNormLog,
231
- defaultPolicy, strategy);
232
- assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
233
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
234
- countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
235
- prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
236
- cTableWksp, cTableWkspSize);
237
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
238
- if (Offtype == set_compressed)
239
- fseMetadata->lastCountSize = countSize;
240
- op += countSize;
241
- fseMetadata->ofType = (symbolEncodingType_e) Offtype;
242
- } }
243
- /* build CTable for MatchLengths */
244
- { U32 MLtype;
245
- unsigned max = MaxML;
246
- size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
247
- DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
248
- nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
249
- MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
250
- countWksp, max, mostFrequent, nbSeq,
251
- MLFSELog, prevEntropy->matchlengthCTable,
252
- ML_defaultNorm, ML_defaultNormLog,
253
- ZSTD_defaultAllowed, strategy);
254
- assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
255
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
256
- countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
257
- prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
258
- cTableWksp, cTableWkspSize);
259
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
260
- if (MLtype == set_compressed)
261
- fseMetadata->lastCountSize = countSize;
262
- op += countSize;
263
- fseMetadata->mlType = (symbolEncodingType_e) MLtype;
264
- } }
265
- assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer));
266
- return op-ostart;
267
- }
268
-
269
-
270
- /** ZSTD_buildSuperBlockEntropy() :
271
- * Builds entropy for the super-block.
272
- * @return : 0 on success or error code */
273
- static size_t
274
- ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
275
- const ZSTD_entropyCTables_t* prevEntropy,
276
- ZSTD_entropyCTables_t* nextEntropy,
277
- const ZSTD_CCtx_params* cctxParams,
278
- ZSTD_entropyCTablesMetadata_t* entropyMetadata,
279
- void* workspace, size_t wkspSize)
280
- {
281
- size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart;
282
- DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy");
283
- entropyMetadata->hufMetadata.hufDesSize =
284
- ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize,
285
- &prevEntropy->huf, &nextEntropy->huf,
286
- &entropyMetadata->hufMetadata,
287
- ZSTD_disableLiteralsCompression(cctxParams),
288
- workspace, wkspSize);
289
- FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed");
290
- entropyMetadata->fseMetadata.fseTablesSize =
291
- ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr,
292
- &prevEntropy->fse, &nextEntropy->fse,
293
- cctxParams,
294
- &entropyMetadata->fseMetadata,
295
- workspace, wkspSize);
296
- FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed");
297
- return 0;
298
- }
299
-
300
22
  /** ZSTD_compressSubBlock_literal() :
301
23
  * Compresses literals section for a sub-block.
302
24
  * When we have to write the Huffman table we will sometimes choose a header
@@ -304,7 +26,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
304
26
  * before we know the table size + compressed size, so we have a bound on the
305
27
  * table size. If we guessed incorrectly, we fall back to uncompressed literals.
306
28
  *
307
- * We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded
29
+ * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
308
30
  * in writing the header, otherwise it is set to 0.
309
31
  *
310
32
  * hufMetadata->hType has literals block type info.
@@ -314,13 +36,14 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
314
36
  * If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block
315
37
  * and the following sub-blocks' literals sections will be Treeless_Literals_Block.
316
38
  * @return : compressed size of literals section of a sub-block
317
- * Or 0 if it unable to compress.
39
+ * Or 0 if unable to compress.
318
40
  * Or error code */
319
- static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
320
- const ZSTD_hufCTablesMetadata_t* hufMetadata,
321
- const BYTE* literals, size_t litSize,
322
- void* dst, size_t dstSize,
323
- const int bmi2, int writeEntropy, int* entropyWritten)
41
+ static size_t
42
+ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
43
+ const ZSTD_hufCTablesMetadata_t* hufMetadata,
44
+ const BYTE* literals, size_t litSize,
45
+ void* dst, size_t dstSize,
46
+ const int bmi2, int writeEntropy, int* entropyWritten)
324
47
  {
325
48
  size_t const header = writeEntropy ? 200 : 0;
326
49
  size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header));
@@ -331,8 +54,6 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
331
54
  symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat;
332
55
  size_t cLitSize = 0;
333
56
 
334
- (void)bmi2; /* TODO bmi2... */
335
-
336
57
  DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy);
337
58
 
338
59
  *entropyWritten = 0;
@@ -354,9 +75,9 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
354
75
  DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
355
76
  }
356
77
 
357
- /* TODO bmi2 */
358
- { const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable)
359
- : HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable);
78
+ { int const flags = bmi2 ? HUF_flags_bmi2 : 0;
79
+ const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags)
80
+ : HUF_compress4X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags);
360
81
  op += cSize;
361
82
  cLitSize += cSize;
362
83
  if (cSize == 0 || ERR_isError(cSize)) {
@@ -381,7 +102,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
381
102
  switch(lhSize)
382
103
  {
383
104
  case 3: /* 2 - 2 - 10 - 10 */
384
- { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
105
+ { U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
385
106
  MEM_writeLE24(ostart, lhc);
386
107
  break;
387
108
  }
@@ -401,25 +122,30 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
401
122
  }
402
123
  *entropyWritten = 1;
403
124
  DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart));
404
- return op-ostart;
125
+ return (size_t)(op-ostart);
405
126
  }
406
127
 
407
- static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef* sequences, size_t nbSeq, size_t litSize, int lastSequence) {
408
- const seqDef* const sstart = sequences;
409
- const seqDef* const send = sequences + nbSeq;
410
- const seqDef* sp = sstart;
128
+ static size_t
129
+ ZSTD_seqDecompressedSize(seqStore_t const* seqStore,
130
+ const seqDef* sequences, size_t nbSeqs,
131
+ size_t litSize, int lastSubBlock)
132
+ {
411
133
  size_t matchLengthSum = 0;
412
134
  size_t litLengthSum = 0;
413
- while (send-sp > 0) {
414
- ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
135
+ size_t n;
136
+ for (n=0; n<nbSeqs; n++) {
137
+ const ZSTD_sequenceLength seqLen = ZSTD_getSequenceLength(seqStore, sequences+n);
415
138
  litLengthSum += seqLen.litLength;
416
139
  matchLengthSum += seqLen.matchLength;
417
- sp++;
418
140
  }
419
- assert(litLengthSum <= litSize);
420
- if (!lastSequence) {
141
+ DEBUGLOG(5, "ZSTD_seqDecompressedSize: %u sequences from %p: %u literals + %u matchlength",
142
+ (unsigned)nbSeqs, (const void*)sequences,
143
+ (unsigned)litLengthSum, (unsigned)matchLengthSum);
144
+ if (!lastSubBlock)
421
145
  assert(litLengthSum == litSize);
422
- }
146
+ else
147
+ assert(litLengthSum <= litSize);
148
+ (void)litLengthSum;
423
149
  return matchLengthSum + litSize;
424
150
  }
425
151
 
@@ -433,13 +159,14 @@ static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef*
433
159
  * @return : compressed size of sequences section of a sub-block
434
160
  * Or 0 if it is unable to compress
435
161
  * Or error code. */
436
- static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
437
- const ZSTD_fseCTablesMetadata_t* fseMetadata,
438
- const seqDef* sequences, size_t nbSeq,
439
- const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
440
- const ZSTD_CCtx_params* cctxParams,
441
- void* dst, size_t dstCapacity,
442
- const int bmi2, int writeEntropy, int* entropyWritten)
162
+ static size_t
163
+ ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
164
+ const ZSTD_fseCTablesMetadata_t* fseMetadata,
165
+ const seqDef* sequences, size_t nbSeq,
166
+ const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
167
+ const ZSTD_CCtx_params* cctxParams,
168
+ void* dst, size_t dstCapacity,
169
+ const int bmi2, int writeEntropy, int* entropyWritten)
443
170
  {
444
171
  const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
445
172
  BYTE* const ostart = (BYTE*)dst;
@@ -453,14 +180,14 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
453
180
  /* Sequences Header */
454
181
  RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
455
182
  dstSize_tooSmall, "");
456
- if (nbSeq < 0x7F)
183
+ if (nbSeq < 128)
457
184
  *op++ = (BYTE)nbSeq;
458
185
  else if (nbSeq < LONGNBSEQ)
459
186
  op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
460
187
  else
461
188
  op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
462
189
  if (nbSeq==0) {
463
- return op - ostart;
190
+ return (size_t)(op - ostart);
464
191
  }
465
192
 
466
193
  /* seqHead : flags for FSE encoding type */
@@ -482,7 +209,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
482
209
  }
483
210
 
484
211
  { size_t const bitstreamSize = ZSTD_encodeSequences(
485
- op, oend - op,
212
+ op, (size_t)(oend - op),
486
213
  fseTables->matchlengthCTable, mlCode,
487
214
  fseTables->offcodeCTable, ofCode,
488
215
  fseTables->litlengthCTable, llCode,
@@ -526,7 +253,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
526
253
  #endif
527
254
 
528
255
  *entropyWritten = 1;
529
- return op - ostart;
256
+ return (size_t)(op - ostart);
530
257
  }
531
258
 
532
259
  /** ZSTD_compressSubBlock() :
@@ -552,7 +279,8 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
552
279
  litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock);
553
280
  { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,
554
281
  &entropyMetadata->hufMetadata, literals, litSize,
555
- op, oend-op, bmi2, writeLitEntropy, litEntropyWritten);
282
+ op, (size_t)(oend-op),
283
+ bmi2, writeLitEntropy, litEntropyWritten);
556
284
  FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed");
557
285
  if (cLitSize == 0) return 0;
558
286
  op += cLitSize;
@@ -562,18 +290,18 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
562
290
  sequences, nbSeq,
563
291
  llCode, mlCode, ofCode,
564
292
  cctxParams,
565
- op, oend-op,
293
+ op, (size_t)(oend-op),
566
294
  bmi2, writeSeqEntropy, seqEntropyWritten);
567
295
  FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed");
568
296
  if (cSeqSize == 0) return 0;
569
297
  op += cSeqSize;
570
298
  }
571
299
  /* Write block header */
572
- { size_t cSize = (op-ostart)-ZSTD_blockHeaderSize;
300
+ { size_t cSize = (size_t)(op-ostart) - ZSTD_blockHeaderSize;
573
301
  U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
574
302
  MEM_writeLE24(ostart, cBlockHeader24);
575
303
  }
576
- return op-ostart;
304
+ return (size_t)(op-ostart);
577
305
  }
578
306
 
579
307
  static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,
@@ -602,7 +330,7 @@ static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t lit
602
330
  static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
603
331
  const BYTE* codeTable, unsigned maxCode,
604
332
  size_t nbSeq, const FSE_CTable* fseCTable,
605
- const U32* additionalBits,
333
+ const U8* additionalBits,
606
334
  short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
607
335
  void* workspace, size_t wkspSize)
608
336
  {
@@ -643,8 +371,9 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
643
371
  void* workspace, size_t wkspSize,
644
372
  int writeEntropy)
645
373
  {
646
- size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
374
+ size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
647
375
  size_t cSeqSizeEstimate = 0;
376
+ if (nbSeq == 0) return sequencesSectionHeaderSize;
648
377
  cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
649
378
  nbSeq, fseTables->offcodeCTable, NULL,
650
379
  OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
@@ -661,7 +390,11 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
661
390
  return cSeqSizeEstimate + sequencesSectionHeaderSize;
662
391
  }
663
392
 
664
- static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
393
+ typedef struct {
394
+ size_t estLitSize;
395
+ size_t estBlockSize;
396
+ } EstimatedBlockSize;
397
+ static EstimatedBlockSize ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
665
398
  const BYTE* ofCodeTable,
666
399
  const BYTE* llCodeTable,
667
400
  const BYTE* mlCodeTable,
@@ -669,15 +402,17 @@ static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
669
402
  const ZSTD_entropyCTables_t* entropy,
670
403
  const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
671
404
  void* workspace, size_t wkspSize,
672
- int writeLitEntropy, int writeSeqEntropy) {
673
- size_t cSizeEstimate = 0;
674
- cSizeEstimate += ZSTD_estimateSubBlockSize_literal(literals, litSize,
675
- &entropy->huf, &entropyMetadata->hufMetadata,
676
- workspace, wkspSize, writeLitEntropy);
677
- cSizeEstimate += ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
405
+ int writeLitEntropy, int writeSeqEntropy)
406
+ {
407
+ EstimatedBlockSize ebs;
408
+ ebs.estLitSize = ZSTD_estimateSubBlockSize_literal(literals, litSize,
409
+ &entropy->huf, &entropyMetadata->hufMetadata,
410
+ workspace, wkspSize, writeLitEntropy);
411
+ ebs.estBlockSize = ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
678
412
  nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
679
413
  workspace, wkspSize, writeSeqEntropy);
680
- return cSizeEstimate + ZSTD_blockHeaderSize;
414
+ ebs.estBlockSize += ebs.estLitSize + ZSTD_blockHeaderSize;
415
+ return ebs;
681
416
  }
682
417
 
683
418
  static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata)
@@ -691,13 +426,56 @@ static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMe
691
426
  return 0;
692
427
  }
693
428
 
429
+ static size_t countLiterals(seqStore_t const* seqStore, const seqDef* sp, size_t seqCount)
430
+ {
431
+ size_t n, total = 0;
432
+ assert(sp != NULL);
433
+ for (n=0; n<seqCount; n++) {
434
+ total += ZSTD_getSequenceLength(seqStore, sp+n).litLength;
435
+ }
436
+ DEBUGLOG(6, "countLiterals for %zu sequences from %p => %zu bytes", seqCount, (const void*)sp, total);
437
+ return total;
438
+ }
439
+
440
+ #define BYTESCALE 256
441
+
442
+ static size_t sizeBlockSequences(const seqDef* sp, size_t nbSeqs,
443
+ size_t targetBudget, size_t avgLitCost, size_t avgSeqCost,
444
+ int firstSubBlock)
445
+ {
446
+ size_t n, budget = 0, inSize=0;
447
+ /* entropy headers */
448
+ size_t const headerSize = (size_t)firstSubBlock * 120 * BYTESCALE; /* generous estimate */
449
+ assert(firstSubBlock==0 || firstSubBlock==1);
450
+ budget += headerSize;
451
+
452
+ /* first sequence => at least one sequence*/
453
+ budget += sp[0].litLength * avgLitCost + avgSeqCost;
454
+ if (budget > targetBudget) return 1;
455
+ inSize = sp[0].litLength + (sp[0].mlBase+MINMATCH);
456
+
457
+ /* loop over sequences */
458
+ for (n=1; n<nbSeqs; n++) {
459
+ size_t currentCost = sp[n].litLength * avgLitCost + avgSeqCost;
460
+ budget += currentCost;
461
+ inSize += sp[n].litLength + (sp[n].mlBase+MINMATCH);
462
+ /* stop when sub-block budget is reached */
463
+ if ( (budget > targetBudget)
464
+ /* though continue to expand until the sub-block is deemed compressible */
465
+ && (budget < inSize * BYTESCALE) )
466
+ break;
467
+ }
468
+
469
+ return n;
470
+ }
471
+
694
472
  /** ZSTD_compressSubBlock_multi() :
695
473
  * Breaks super-block into multiple sub-blocks and compresses them.
696
- * Entropy will be written to the first block.
697
- * The following blocks will use repeat mode to compress.
698
- * All sub-blocks are compressed blocks (no raw or rle blocks).
699
- * @return : compressed size of the super block (which is multiple ZSTD blocks)
700
- * Or 0 if it failed to compress. */
474
+ * Entropy will be written into the first block.
475
+ * The following blocks use repeat_mode to compress.
476
+ * Sub-blocks are all compressed, except the last one when beneficial.
477
+ * @return : compressed size of the super block (which features multiple ZSTD blocks)
478
+ * or 0 if it failed to compress. */
701
479
  static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
702
480
  const ZSTD_compressedBlockState_t* prevCBlock,
703
481
  ZSTD_compressedBlockState_t* nextCBlock,
@@ -710,10 +488,12 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
710
488
  {
711
489
  const seqDef* const sstart = seqStorePtr->sequencesStart;
712
490
  const seqDef* const send = seqStorePtr->sequences;
713
- const seqDef* sp = sstart;
491
+ const seqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */
492
+ size_t const nbSeqs = (size_t)(send - sstart);
714
493
  const BYTE* const lstart = seqStorePtr->litStart;
715
494
  const BYTE* const lend = seqStorePtr->lit;
716
495
  const BYTE* lp = lstart;
496
+ size_t const nbLiterals = (size_t)(lend - lstart);
717
497
  BYTE const* ip = (BYTE const*)src;
718
498
  BYTE const* const iend = ip + srcSize;
719
499
  BYTE* const ostart = (BYTE*)dst;
@@ -722,115 +502,174 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
722
502
  const BYTE* llCodePtr = seqStorePtr->llCode;
723
503
  const BYTE* mlCodePtr = seqStorePtr->mlCode;
724
504
  const BYTE* ofCodePtr = seqStorePtr->ofCode;
725
- size_t targetCBlockSize = cctxParams->targetCBlockSize;
726
- size_t litSize, seqCount;
727
- int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed;
505
+ size_t const minTarget = ZSTD_TARGETCBLOCKSIZE_MIN; /* enforce minimum size, to reduce undesirable side effects */
506
+ size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize);
507
+ int writeLitEntropy = (entropyMetadata->hufMetadata.hType == set_compressed);
728
508
  int writeSeqEntropy = 1;
729
- int lastSequence = 0;
730
-
731
- DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)",
732
- (unsigned)(lend-lp), (unsigned)(send-sstart));
733
-
734
- litSize = 0;
735
- seqCount = 0;
736
- do {
737
- size_t cBlockSizeEstimate = 0;
738
- if (sstart == send) {
739
- lastSequence = 1;
740
- } else {
741
- const seqDef* const sequence = sp + seqCount;
742
- lastSequence = sequence == send - 1;
743
- litSize += ZSTD_getSequenceLength(seqStorePtr, sequence).litLength;
744
- seqCount++;
745
- }
746
- if (lastSequence) {
747
- assert(lp <= lend);
748
- assert(litSize <= (size_t)(lend - lp));
749
- litSize = (size_t)(lend - lp);
509
+
510
+ DEBUGLOG(5, "ZSTD_compressSubBlock_multi (srcSize=%u, litSize=%u, nbSeq=%u)",
511
+ (unsigned)srcSize, (unsigned)(lend-lstart), (unsigned)(send-sstart));
512
+
513
+ /* let's start by a general estimation for the full block */
514
+ if (nbSeqs > 0) {
515
+ EstimatedBlockSize const ebs =
516
+ ZSTD_estimateSubBlockSize(lp, nbLiterals,
517
+ ofCodePtr, llCodePtr, mlCodePtr, nbSeqs,
518
+ &nextCBlock->entropy, entropyMetadata,
519
+ workspace, wkspSize,
520
+ writeLitEntropy, writeSeqEntropy);
521
+ /* quick estimation */
522
+ size_t const avgLitCost = nbLiterals ? (ebs.estLitSize * BYTESCALE) / nbLiterals : BYTESCALE;
523
+ size_t const avgSeqCost = ((ebs.estBlockSize - ebs.estLitSize) * BYTESCALE) / nbSeqs;
524
+ const size_t nbSubBlocks = MAX((ebs.estBlockSize + (targetCBlockSize/2)) / targetCBlockSize, 1);
525
+ size_t n, avgBlockBudget, blockBudgetSupp=0;
526
+ avgBlockBudget = (ebs.estBlockSize * BYTESCALE) / nbSubBlocks;
527
+ DEBUGLOG(5, "estimated fullblock size=%u bytes ; avgLitCost=%.2f ; avgSeqCost=%.2f ; targetCBlockSize=%u, nbSubBlocks=%u ; avgBlockBudget=%.0f bytes",
528
+ (unsigned)ebs.estBlockSize, (double)avgLitCost/BYTESCALE, (double)avgSeqCost/BYTESCALE,
529
+ (unsigned)targetCBlockSize, (unsigned)nbSubBlocks, (double)avgBlockBudget/BYTESCALE);
530
+ /* simplification: if estimates states that the full superblock doesn't compress, just bail out immediately
531
+ * this will result in the production of a single uncompressed block covering @srcSize.*/
532
+ if (ebs.estBlockSize > srcSize) return 0;
533
+
534
+ /* compress and write sub-blocks */
535
+ assert(nbSubBlocks>0);
536
+ for (n=0; n < nbSubBlocks-1; n++) {
537
+ /* determine nb of sequences for current sub-block + nbLiterals from next sequence */
538
+ size_t const seqCount = sizeBlockSequences(sp, (size_t)(send-sp),
539
+ avgBlockBudget + blockBudgetSupp, avgLitCost, avgSeqCost, n==0);
540
+ /* if reached last sequence : break to last sub-block (simplification) */
541
+ assert(seqCount <= (size_t)(send-sp));
542
+ if (sp + seqCount == send) break;
543
+ assert(seqCount > 0);
544
+ /* compress sub-block */
545
+ { int litEntropyWritten = 0;
546
+ int seqEntropyWritten = 0;
547
+ size_t litSize = countLiterals(seqStorePtr, sp, seqCount);
548
+ const size_t decompressedSize =
549
+ ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 0);
550
+ size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
551
+ sp, seqCount,
552
+ lp, litSize,
553
+ llCodePtr, mlCodePtr, ofCodePtr,
554
+ cctxParams,
555
+ op, (size_t)(oend-op),
556
+ bmi2, writeLitEntropy, writeSeqEntropy,
557
+ &litEntropyWritten, &seqEntropyWritten,
558
+ 0);
559
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
560
+
561
+ /* check compressibility, update state components */
562
+ if (cSize > 0 && cSize < decompressedSize) {
563
+ DEBUGLOG(5, "Committed sub-block compressing %u bytes => %u bytes",
564
+ (unsigned)decompressedSize, (unsigned)cSize);
565
+ assert(ip + decompressedSize <= iend);
566
+ ip += decompressedSize;
567
+ lp += litSize;
568
+ op += cSize;
569
+ llCodePtr += seqCount;
570
+ mlCodePtr += seqCount;
571
+ ofCodePtr += seqCount;
572
+ /* Entropy only needs to be written once */
573
+ if (litEntropyWritten) {
574
+ writeLitEntropy = 0;
575
+ }
576
+ if (seqEntropyWritten) {
577
+ writeSeqEntropy = 0;
578
+ }
579
+ sp += seqCount;
580
+ blockBudgetSupp = 0;
581
+ } }
582
+ /* otherwise : do not compress yet, coalesce current sub-block with following one */
750
583
  }
751
- /* I think there is an optimization opportunity here.
752
- * Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful
753
- * since it recalculates estimate from scratch.
754
- * For example, it would recount literal distribution and symbol codes everytime.
755
- */
756
- cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
757
- &nextCBlock->entropy, entropyMetadata,
758
- workspace, wkspSize, writeLitEntropy, writeSeqEntropy);
759
- if (cBlockSizeEstimate > targetCBlockSize || lastSequence) {
760
- int litEntropyWritten = 0;
761
- int seqEntropyWritten = 0;
762
- const size_t decompressedSize = ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSequence);
763
- const size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
764
- sp, seqCount,
765
- lp, litSize,
766
- llCodePtr, mlCodePtr, ofCodePtr,
767
- cctxParams,
768
- op, oend-op,
769
- bmi2, writeLitEntropy, writeSeqEntropy,
770
- &litEntropyWritten, &seqEntropyWritten,
771
- lastBlock && lastSequence);
772
- FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
773
- if (cSize > 0 && cSize < decompressedSize) {
774
- DEBUGLOG(5, "Committed the sub-block");
775
- assert(ip + decompressedSize <= iend);
776
- ip += decompressedSize;
777
- sp += seqCount;
778
- lp += litSize;
779
- op += cSize;
780
- llCodePtr += seqCount;
781
- mlCodePtr += seqCount;
782
- ofCodePtr += seqCount;
783
- litSize = 0;
784
- seqCount = 0;
785
- /* Entropy only needs to be written once */
786
- if (litEntropyWritten) {
787
- writeLitEntropy = 0;
788
- }
789
- if (seqEntropyWritten) {
790
- writeSeqEntropy = 0;
791
- }
584
+ } /* if (nbSeqs > 0) */
585
+
586
+ /* write last block */
587
+ DEBUGLOG(5, "Generate last sub-block: %u sequences remaining", (unsigned)(send - sp));
588
+ { int litEntropyWritten = 0;
589
+ int seqEntropyWritten = 0;
590
+ size_t litSize = (size_t)(lend - lp);
591
+ size_t seqCount = (size_t)(send - sp);
592
+ const size_t decompressedSize =
593
+ ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 1);
594
+ size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
595
+ sp, seqCount,
596
+ lp, litSize,
597
+ llCodePtr, mlCodePtr, ofCodePtr,
598
+ cctxParams,
599
+ op, (size_t)(oend-op),
600
+ bmi2, writeLitEntropy, writeSeqEntropy,
601
+ &litEntropyWritten, &seqEntropyWritten,
602
+ lastBlock);
603
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
604
+
605
+ /* update pointers, the nb of literals borrowed from next sequence must be preserved */
606
+ if (cSize > 0 && cSize < decompressedSize) {
607
+ DEBUGLOG(5, "Last sub-block compressed %u bytes => %u bytes",
608
+ (unsigned)decompressedSize, (unsigned)cSize);
609
+ assert(ip + decompressedSize <= iend);
610
+ ip += decompressedSize;
611
+ lp += litSize;
612
+ op += cSize;
613
+ llCodePtr += seqCount;
614
+ mlCodePtr += seqCount;
615
+ ofCodePtr += seqCount;
616
+ /* Entropy only needs to be written once */
617
+ if (litEntropyWritten) {
618
+ writeLitEntropy = 0;
619
+ }
620
+ if (seqEntropyWritten) {
621
+ writeSeqEntropy = 0;
792
622
  }
623
+ sp += seqCount;
793
624
  }
794
- } while (!lastSequence);
625
+ }
626
+
627
+
795
628
  if (writeLitEntropy) {
796
- DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
629
+ DEBUGLOG(5, "Literal entropy tables were never written");
797
630
  ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
798
631
  }
799
632
  if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
800
633
  /* If we haven't written our entropy tables, then we've violated our contract and
801
634
  * must emit an uncompressed block.
802
635
  */
803
- DEBUGLOG(5, "ZSTD_compressSubBlock_multi has sequence entropy tables unwritten");
636
+ DEBUGLOG(5, "Sequence entropy tables were never written => cancel, emit an uncompressed block");
804
637
  return 0;
805
638
  }
639
+
806
640
  if (ip < iend) {
807
- size_t const cSize = ZSTD_noCompressBlock(op, oend - op, ip, iend - ip, lastBlock);
808
- DEBUGLOG(5, "ZSTD_compressSubBlock_multi last sub-block uncompressed, %zu bytes", (size_t)(iend - ip));
641
+ /* some data left : last part of the block sent uncompressed */
642
+ size_t const rSize = (size_t)((iend - ip));
643
+ size_t const cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, rSize, lastBlock);
644
+ DEBUGLOG(5, "Generate last uncompressed sub-block of %u bytes", (unsigned)(rSize));
809
645
  FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
810
646
  assert(cSize != 0);
811
647
  op += cSize;
812
648
  /* We have to regenerate the repcodes because we've skipped some sequences */
813
649
  if (sp < send) {
814
- seqDef const* seq;
650
+ const seqDef* seq;
815
651
  repcodes_t rep;
816
652
  ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
817
653
  for (seq = sstart; seq < sp; ++seq) {
818
- rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
654
+ ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
819
655
  }
820
656
  ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
821
657
  }
822
658
  }
823
- DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
824
- return op-ostart;
659
+
660
+ DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed all subBlocks: total compressed size = %u",
661
+ (unsigned)(op-ostart));
662
+ return (size_t)(op-ostart);
825
663
  }
826
664
 
827
665
  size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
828
666
  void* dst, size_t dstCapacity,
829
- void const* src, size_t srcSize,
830
- unsigned lastBlock) {
667
+ const void* src, size_t srcSize,
668
+ unsigned lastBlock)
669
+ {
831
670
  ZSTD_entropyCTablesMetadata_t entropyMetadata;
832
671
 
833
- FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore,
672
+ FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,
834
673
  &zc->blockState.prevCBlock->entropy,
835
674
  &zc->blockState.nextCBlock->entropy,
836
675
  &zc->appliedParams,