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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +35 -0
- data/README.md +2 -2
- data/ext/zstdruby/libzstd/Makefile +274 -107
- data/ext/zstdruby/libzstd/README.md +75 -16
- data/ext/zstdruby/libzstd/common/bitstream.h +59 -51
- data/ext/zstdruby/libzstd/common/compiler.h +154 -5
- data/ext/zstdruby/libzstd/common/cpu.h +1 -3
- data/ext/zstdruby/libzstd/common/debug.c +11 -31
- data/ext/zstdruby/libzstd/common/debug.h +22 -49
- data/ext/zstdruby/libzstd/common/entropy_common.c +201 -75
- data/ext/zstdruby/libzstd/common/error_private.c +3 -1
- data/ext/zstdruby/libzstd/common/error_private.h +7 -3
- data/ext/zstdruby/libzstd/common/fse.h +50 -42
- data/ext/zstdruby/libzstd/common/fse_decompress.c +134 -50
- data/ext/zstdruby/libzstd/common/huf.h +41 -38
- data/ext/zstdruby/libzstd/common/mem.h +68 -22
- data/ext/zstdruby/libzstd/common/pool.c +30 -20
- data/ext/zstdruby/libzstd/common/pool.h +3 -3
- data/ext/zstdruby/libzstd/common/threading.c +51 -4
- data/ext/zstdruby/libzstd/common/threading.h +36 -4
- data/ext/zstdruby/libzstd/common/xxhash.c +39 -89
- data/ext/zstdruby/libzstd/common/xxhash.h +12 -32
- data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +231 -72
- data/ext/zstdruby/libzstd/common/zstd_trace.c +42 -0
- data/ext/zstdruby/libzstd/common/zstd_trace.h +152 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +47 -63
- data/ext/zstdruby/libzstd/compress/hist.c +41 -63
- data/ext/zstdruby/libzstd/compress/hist.h +13 -33
- data/ext/zstdruby/libzstd/compress/huf_compress.c +288 -172
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +2504 -1626
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +446 -85
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +433 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +849 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +561 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +82 -60
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +106 -80
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +411 -105
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +21 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +296 -207
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +14 -3
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +260 -148
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +153 -440
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +29 -110
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +356 -238
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +20 -16
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +641 -238
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +600 -371
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +8 -5
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +40 -9
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +197 -78
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +52 -7
- data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +84 -66
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +58 -36
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +60 -31
- data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
- data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +8 -4
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +115 -111
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +28 -14
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +28 -14
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +36 -19
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +122 -107
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +2 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +29 -23
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +34 -24
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
- data/ext/zstdruby/libzstd/libzstd.pc.in +2 -1
- data/ext/zstdruby/libzstd/zstd.h +655 -118
- data/lib/zstd-ruby/version.rb +1 -1
- data/zstd-ruby.gemspec +1 -1
- metadata +20 -10
- data/.travis.yml +0 -14
|
@@ -1,40 +1,20 @@
|
|
|
1
1
|
/* ******************************************************************
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* Redistributions in binary form must reproduce the above
|
|
15
|
-
copyright notice, this list of conditions and the following disclaimer
|
|
16
|
-
in the documentation and/or other materials provided with the
|
|
17
|
-
distribution.
|
|
18
|
-
|
|
19
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20
|
-
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21
|
-
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
22
|
-
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
23
|
-
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
24
|
-
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
25
|
-
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
26
|
-
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
27
|
-
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
-
|
|
31
|
-
You can contact the author at :
|
|
32
|
-
- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
33
|
-
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
|
2
|
+
* hist : Histogram functions
|
|
3
|
+
* part of Finite State Entropy project
|
|
4
|
+
* Copyright (c) 2013-2021, Yann Collet, Facebook, Inc.
|
|
5
|
+
*
|
|
6
|
+
* You can contact the author at :
|
|
7
|
+
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
8
|
+
* - Public forum : https://groups.google.com/forum/#!forum/lz4c
|
|
9
|
+
*
|
|
10
|
+
* This source code is licensed under both the BSD-style license (found in the
|
|
11
|
+
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
12
|
+
* in the COPYING file in the root directory of this source tree).
|
|
13
|
+
* You may select, at your option, one of the above-listed licenses.
|
|
34
14
|
****************************************************************** */
|
|
35
15
|
|
|
36
16
|
/* --- dependencies --- */
|
|
37
|
-
#include
|
|
17
|
+
#include "../common/zstd_deps.h" /* size_t */
|
|
38
18
|
|
|
39
19
|
|
|
40
20
|
/* --- simple histogram functions --- */
|
|
@@ -1,35 +1,15 @@
|
|
|
1
1
|
/* ******************************************************************
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* Redistributions in binary form must reproduce the above
|
|
14
|
-
copyright notice, this list of conditions and the following disclaimer
|
|
15
|
-
in the documentation and/or other materials provided with the
|
|
16
|
-
distribution.
|
|
17
|
-
|
|
18
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
-
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
-
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
-
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
-
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
-
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
-
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
-
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
-
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
-
|
|
30
|
-
You can contact the author at :
|
|
31
|
-
- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
32
|
-
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
|
2
|
+
* Huffman encoder, part of New Generation Entropy library
|
|
3
|
+
* Copyright (c) 2013-2021, Yann Collet, Facebook, Inc.
|
|
4
|
+
*
|
|
5
|
+
* You can contact the author at :
|
|
6
|
+
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
7
|
+
* - Public forum : https://groups.google.com/forum/#!forum/lz4c
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under both the BSD-style license (found in the
|
|
10
|
+
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
11
|
+
* in the COPYING file in the root directory of this source tree).
|
|
12
|
+
* You may select, at your option, one of the above-listed licenses.
|
|
33
13
|
****************************************************************** */
|
|
34
14
|
|
|
35
15
|
/* **************************************************************
|
|
@@ -43,16 +23,15 @@
|
|
|
43
23
|
/* **************************************************************
|
|
44
24
|
* Includes
|
|
45
25
|
****************************************************************/
|
|
46
|
-
#include
|
|
47
|
-
#include
|
|
48
|
-
#include "
|
|
49
|
-
#include "bitstream.h"
|
|
26
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */
|
|
27
|
+
#include "../common/compiler.h"
|
|
28
|
+
#include "../common/bitstream.h"
|
|
50
29
|
#include "hist.h"
|
|
51
30
|
#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
|
|
52
|
-
#include "fse.h" /* header compression */
|
|
31
|
+
#include "../common/fse.h" /* header compression */
|
|
53
32
|
#define HUF_STATIC_LINKING_ONLY
|
|
54
|
-
#include "huf.h"
|
|
55
|
-
#include "error_private.h"
|
|
33
|
+
#include "../common/huf.h"
|
|
34
|
+
#include "../common/error_private.h"
|
|
56
35
|
|
|
57
36
|
|
|
58
37
|
/* **************************************************************
|
|
@@ -60,8 +39,6 @@
|
|
|
60
39
|
****************************************************************/
|
|
61
40
|
#define HUF_isError ERR_isError
|
|
62
41
|
#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
|
|
63
|
-
#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
|
|
64
|
-
#define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
|
|
65
42
|
|
|
66
43
|
|
|
67
44
|
/* **************************************************************
|
|
@@ -92,7 +69,7 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight
|
|
|
92
69
|
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
|
|
93
70
|
|
|
94
71
|
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
|
|
95
|
-
|
|
72
|
+
U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)];
|
|
96
73
|
|
|
97
74
|
unsigned count[HUF_TABLELOG_MAX+1];
|
|
98
75
|
S16 norm[HUF_TABLELOG_MAX+1];
|
|
@@ -107,29 +84,24 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight
|
|
|
107
84
|
}
|
|
108
85
|
|
|
109
86
|
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
|
|
110
|
-
CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) );
|
|
87
|
+
CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) );
|
|
111
88
|
|
|
112
89
|
/* Write table description header */
|
|
113
|
-
{ CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) );
|
|
90
|
+
{ CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) );
|
|
114
91
|
op += hSize;
|
|
115
92
|
}
|
|
116
93
|
|
|
117
94
|
/* Compress */
|
|
118
95
|
CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) );
|
|
119
|
-
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) );
|
|
96
|
+
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) );
|
|
120
97
|
if (cSize == 0) return 0; /* not enough space for compressed data */
|
|
121
98
|
op += cSize;
|
|
122
99
|
}
|
|
123
100
|
|
|
124
|
-
return op-ostart;
|
|
101
|
+
return (size_t)(op-ostart);
|
|
125
102
|
}
|
|
126
103
|
|
|
127
104
|
|
|
128
|
-
struct HUF_CElt_s {
|
|
129
|
-
U16 val;
|
|
130
|
-
BYTE nbBits;
|
|
131
|
-
}; /* typedef'd to HUF_CElt within "huf.h" */
|
|
132
|
-
|
|
133
105
|
/*! HUF_writeCTable() :
|
|
134
106
|
`CTable` : Huffman tree to save, using huf representation.
|
|
135
107
|
@return : size of saved CTable */
|
|
@@ -169,7 +141,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
|
|
169
141
|
}
|
|
170
142
|
|
|
171
143
|
|
|
172
|
-
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize)
|
|
144
|
+
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)
|
|
173
145
|
{
|
|
174
146
|
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
|
|
175
147
|
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
|
|
@@ -178,6 +150,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
|
|
|
178
150
|
|
|
179
151
|
/* get symbol weights */
|
|
180
152
|
CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));
|
|
153
|
+
*hasZeroWeights = (rankVal[0] > 0);
|
|
181
154
|
|
|
182
155
|
/* check result */
|
|
183
156
|
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
|
@@ -186,15 +159,15 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
|
|
|
186
159
|
/* Prepare base value per rank */
|
|
187
160
|
{ U32 n, nextRankStart = 0;
|
|
188
161
|
for (n=1; n<=tableLog; n++) {
|
|
189
|
-
U32
|
|
162
|
+
U32 curr = nextRankStart;
|
|
190
163
|
nextRankStart += (rankVal[n] << (n-1));
|
|
191
|
-
rankVal[n] =
|
|
164
|
+
rankVal[n] = curr;
|
|
192
165
|
} }
|
|
193
166
|
|
|
194
167
|
/* fill nbBits */
|
|
195
168
|
{ U32 n; for (n=0; n<nbSymbols; n++) {
|
|
196
169
|
const U32 w = huffWeight[n];
|
|
197
|
-
CTable[n].nbBits = (BYTE)(tableLog + 1 - w);
|
|
170
|
+
CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0);
|
|
198
171
|
} }
|
|
199
172
|
|
|
200
173
|
/* fill val */
|
|
@@ -232,106 +205,202 @@ typedef struct nodeElt_s {
|
|
|
232
205
|
BYTE nbBits;
|
|
233
206
|
} nodeElt;
|
|
234
207
|
|
|
208
|
+
/**
|
|
209
|
+
* HUF_setMaxHeight():
|
|
210
|
+
* Enforces maxNbBits on the Huffman tree described in huffNode.
|
|
211
|
+
*
|
|
212
|
+
* It sets all nodes with nbBits > maxNbBits to be maxNbBits. Then it adjusts
|
|
213
|
+
* the tree to so that it is a valid canonical Huffman tree.
|
|
214
|
+
*
|
|
215
|
+
* @pre The sum of the ranks of each symbol == 2^largestBits,
|
|
216
|
+
* where largestBits == huffNode[lastNonNull].nbBits.
|
|
217
|
+
* @post The sum of the ranks of each symbol == 2^largestBits,
|
|
218
|
+
* where largestBits is the return value <= maxNbBits.
|
|
219
|
+
*
|
|
220
|
+
* @param huffNode The Huffman tree modified in place to enforce maxNbBits.
|
|
221
|
+
* @param lastNonNull The symbol with the lowest count in the Huffman tree.
|
|
222
|
+
* @param maxNbBits The maximum allowed number of bits, which the Huffman tree
|
|
223
|
+
* may not respect. After this function the Huffman tree will
|
|
224
|
+
* respect maxNbBits.
|
|
225
|
+
* @return The maximum number of bits of the Huffman tree after adjustment,
|
|
226
|
+
* necessarily no more than maxNbBits.
|
|
227
|
+
*/
|
|
235
228
|
static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
|
236
229
|
{
|
|
237
230
|
const U32 largestBits = huffNode[lastNonNull].nbBits;
|
|
238
|
-
|
|
231
|
+
/* early exit : no elt > maxNbBits, so the tree is already valid. */
|
|
232
|
+
if (largestBits <= maxNbBits) return largestBits;
|
|
239
233
|
|
|
240
234
|
/* there are several too large elements (at least >= 2) */
|
|
241
235
|
{ int totalCost = 0;
|
|
242
236
|
const U32 baseCost = 1 << (largestBits - maxNbBits);
|
|
243
|
-
|
|
237
|
+
int n = (int)lastNonNull;
|
|
244
238
|
|
|
239
|
+
/* Adjust any ranks > maxNbBits to maxNbBits.
|
|
240
|
+
* Compute totalCost, which is how far the sum of the ranks is
|
|
241
|
+
* we are over 2^largestBits after adjust the offending ranks.
|
|
242
|
+
*/
|
|
245
243
|
while (huffNode[n].nbBits > maxNbBits) {
|
|
246
244
|
totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));
|
|
247
245
|
huffNode[n].nbBits = (BYTE)maxNbBits;
|
|
248
|
-
n
|
|
249
|
-
}
|
|
250
|
-
|
|
246
|
+
n--;
|
|
247
|
+
}
|
|
248
|
+
/* n stops at huffNode[n].nbBits <= maxNbBits */
|
|
249
|
+
assert(huffNode[n].nbBits <= maxNbBits);
|
|
250
|
+
/* n end at index of smallest symbol using < maxNbBits */
|
|
251
|
+
while (huffNode[n].nbBits == maxNbBits) --n;
|
|
251
252
|
|
|
252
|
-
/* renorm totalCost
|
|
253
|
-
|
|
253
|
+
/* renorm totalCost from 2^largestBits to 2^maxNbBits
|
|
254
|
+
* note : totalCost is necessarily a multiple of baseCost */
|
|
255
|
+
assert((totalCost & (baseCost - 1)) == 0);
|
|
256
|
+
totalCost >>= (largestBits - maxNbBits);
|
|
257
|
+
assert(totalCost > 0);
|
|
254
258
|
|
|
255
259
|
/* repay normalized cost */
|
|
256
260
|
{ U32 const noSymbol = 0xF0F0F0F0;
|
|
257
261
|
U32 rankLast[HUF_TABLELOG_MAX+2];
|
|
258
|
-
int pos;
|
|
259
262
|
|
|
260
|
-
/* Get pos of last (smallest) symbol per rank */
|
|
261
|
-
|
|
263
|
+
/* Get pos of last (smallest = lowest cum. count) symbol per rank */
|
|
264
|
+
ZSTD_memset(rankLast, 0xF0, sizeof(rankLast));
|
|
262
265
|
{ U32 currentNbBits = maxNbBits;
|
|
266
|
+
int pos;
|
|
263
267
|
for (pos=n ; pos >= 0; pos--) {
|
|
264
268
|
if (huffNode[pos].nbBits >= currentNbBits) continue;
|
|
265
269
|
currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */
|
|
266
|
-
rankLast[maxNbBits-currentNbBits] = pos;
|
|
270
|
+
rankLast[maxNbBits-currentNbBits] = (U32)pos;
|
|
267
271
|
} }
|
|
268
272
|
|
|
269
273
|
while (totalCost > 0) {
|
|
270
|
-
|
|
274
|
+
/* Try to reduce the next power of 2 above totalCost because we
|
|
275
|
+
* gain back half the rank.
|
|
276
|
+
*/
|
|
277
|
+
U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1;
|
|
271
278
|
for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {
|
|
272
|
-
U32 highPos = rankLast[nBitsToDecrease];
|
|
273
|
-
U32 lowPos = rankLast[nBitsToDecrease-1];
|
|
279
|
+
U32 const highPos = rankLast[nBitsToDecrease];
|
|
280
|
+
U32 const lowPos = rankLast[nBitsToDecrease-1];
|
|
274
281
|
if (highPos == noSymbol) continue;
|
|
282
|
+
/* Decrease highPos if no symbols of lowPos or if it is
|
|
283
|
+
* not cheaper to remove 2 lowPos than highPos.
|
|
284
|
+
*/
|
|
275
285
|
if (lowPos == noSymbol) break;
|
|
276
286
|
{ U32 const highTotal = huffNode[highPos].count;
|
|
277
287
|
U32 const lowTotal = 2 * huffNode[lowPos].count;
|
|
278
288
|
if (highTotal <= lowTotal) break;
|
|
279
289
|
} }
|
|
280
290
|
/* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
|
|
291
|
+
assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1);
|
|
281
292
|
/* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
|
|
282
293
|
while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))
|
|
283
|
-
nBitsToDecrease
|
|
294
|
+
nBitsToDecrease++;
|
|
295
|
+
assert(rankLast[nBitsToDecrease] != noSymbol);
|
|
296
|
+
/* Increase the number of bits to gain back half the rank cost. */
|
|
284
297
|
totalCost -= 1 << (nBitsToDecrease-1);
|
|
298
|
+
huffNode[rankLast[nBitsToDecrease]].nbBits++;
|
|
299
|
+
|
|
300
|
+
/* Fix up the new rank.
|
|
301
|
+
* If the new rank was empty, this symbol is now its smallest.
|
|
302
|
+
* Otherwise, this symbol will be the largest in the new rank so no adjustment.
|
|
303
|
+
*/
|
|
285
304
|
if (rankLast[nBitsToDecrease-1] == noSymbol)
|
|
286
|
-
rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease];
|
|
287
|
-
|
|
305
|
+
rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease];
|
|
306
|
+
/* Fix up the old rank.
|
|
307
|
+
* If the symbol was at position 0, meaning it was the highest weight symbol in the tree,
|
|
308
|
+
* it must be the only symbol in its rank, so the old rank now has no symbols.
|
|
309
|
+
* Otherwise, since the Huffman nodes are sorted by count, the previous position is now
|
|
310
|
+
* the smallest node in the rank. If the previous position belongs to a different rank,
|
|
311
|
+
* then the rank is now empty.
|
|
312
|
+
*/
|
|
288
313
|
if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */
|
|
289
314
|
rankLast[nBitsToDecrease] = noSymbol;
|
|
290
315
|
else {
|
|
291
316
|
rankLast[nBitsToDecrease]--;
|
|
292
317
|
if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease)
|
|
293
318
|
rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */
|
|
294
|
-
|
|
295
|
-
|
|
319
|
+
}
|
|
320
|
+
} /* while (totalCost > 0) */
|
|
321
|
+
|
|
322
|
+
/* If we've removed too much weight, then we have to add it back.
|
|
323
|
+
* To avoid overshooting again, we only adjust the smallest rank.
|
|
324
|
+
* We take the largest nodes from the lowest rank 0 and move them
|
|
325
|
+
* to rank 1. There's guaranteed to be enough rank 0 symbols because
|
|
326
|
+
* TODO.
|
|
327
|
+
*/
|
|
296
328
|
while (totalCost < 0) { /* Sometimes, cost correction overshoot */
|
|
297
|
-
|
|
329
|
+
/* special case : no rank 1 symbol (using maxNbBits-1);
|
|
330
|
+
* let's create one from largest rank 0 (using maxNbBits).
|
|
331
|
+
*/
|
|
332
|
+
if (rankLast[1] == noSymbol) {
|
|
298
333
|
while (huffNode[n].nbBits == maxNbBits) n--;
|
|
299
334
|
huffNode[n+1].nbBits--;
|
|
300
|
-
|
|
335
|
+
assert(n >= 0);
|
|
336
|
+
rankLast[1] = (U32)(n+1);
|
|
301
337
|
totalCost++;
|
|
302
338
|
continue;
|
|
303
339
|
}
|
|
304
340
|
huffNode[ rankLast[1] + 1 ].nbBits--;
|
|
305
341
|
rankLast[1]++;
|
|
306
342
|
totalCost ++;
|
|
307
|
-
|
|
343
|
+
}
|
|
344
|
+
} /* repay normalized cost */
|
|
345
|
+
} /* there are several too large elements (at least >= 2) */
|
|
308
346
|
|
|
309
347
|
return maxNbBits;
|
|
310
348
|
}
|
|
311
349
|
|
|
312
|
-
|
|
313
350
|
typedef struct {
|
|
314
351
|
U32 base;
|
|
315
|
-
U32
|
|
352
|
+
U32 curr;
|
|
316
353
|
} rankPos;
|
|
317
354
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
U32 n;
|
|
355
|
+
typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
|
|
356
|
+
|
|
357
|
+
#define RANK_POSITION_TABLE_SIZE 32
|
|
322
358
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
359
|
+
typedef struct {
|
|
360
|
+
huffNodeTable huffNodeTbl;
|
|
361
|
+
rankPos rankPosition[RANK_POSITION_TABLE_SIZE];
|
|
362
|
+
} HUF_buildCTable_wksp_tables;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* HUF_sort():
|
|
366
|
+
* Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order.
|
|
367
|
+
*
|
|
368
|
+
* @param[out] huffNode Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled.
|
|
369
|
+
* Must have (maxSymbolValue + 1) entries.
|
|
370
|
+
* @param[in] count Histogram of the symbols.
|
|
371
|
+
* @param[in] maxSymbolValue Maximum symbol value.
|
|
372
|
+
* @param rankPosition This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries.
|
|
373
|
+
*/
|
|
374
|
+
static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition)
|
|
375
|
+
{
|
|
376
|
+
int n;
|
|
377
|
+
int const maxSymbolValue1 = (int)maxSymbolValue + 1;
|
|
378
|
+
|
|
379
|
+
/* Compute base and set curr to base.
|
|
380
|
+
* For symbol s let lowerRank = BIT_highbit32(count[n]+1) and rank = lowerRank + 1.
|
|
381
|
+
* Then 2^lowerRank <= count[n]+1 <= 2^rank.
|
|
382
|
+
* We attribute each symbol to lowerRank's base value, because we want to know where
|
|
383
|
+
* each rank begins in the output, so for rank R we want to count ranks R+1 and above.
|
|
384
|
+
*/
|
|
385
|
+
ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);
|
|
386
|
+
for (n = 0; n < maxSymbolValue1; ++n) {
|
|
387
|
+
U32 lowerRank = BIT_highbit32(count[n] + 1);
|
|
388
|
+
rankPosition[lowerRank].base++;
|
|
327
389
|
}
|
|
328
|
-
|
|
329
|
-
for (n=
|
|
330
|
-
|
|
390
|
+
assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0);
|
|
391
|
+
for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) {
|
|
392
|
+
rankPosition[n-1].base += rankPosition[n].base;
|
|
393
|
+
rankPosition[n-1].curr = rankPosition[n-1].base;
|
|
394
|
+
}
|
|
395
|
+
/* Sort */
|
|
396
|
+
for (n = 0; n < maxSymbolValue1; ++n) {
|
|
331
397
|
U32 const c = count[n];
|
|
332
398
|
U32 const r = BIT_highbit32(c+1) + 1;
|
|
333
|
-
U32 pos =
|
|
334
|
-
|
|
399
|
+
U32 pos = rankPosition[r].curr++;
|
|
400
|
+
/* Insert into the correct position in the rank.
|
|
401
|
+
* We have at most 256 symbols, so this insertion should be fine.
|
|
402
|
+
*/
|
|
403
|
+
while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) {
|
|
335
404
|
huffNode[pos] = huffNode[pos-1];
|
|
336
405
|
pos--;
|
|
337
406
|
}
|
|
@@ -343,45 +412,40 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu
|
|
|
343
412
|
|
|
344
413
|
/** HUF_buildCTable_wksp() :
|
|
345
414
|
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
|
|
346
|
-
* `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as
|
|
415
|
+
* `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables).
|
|
347
416
|
*/
|
|
348
417
|
#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
|
|
349
|
-
|
|
350
|
-
|
|
418
|
+
|
|
419
|
+
/* HUF_buildTree():
|
|
420
|
+
* Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree.
|
|
421
|
+
*
|
|
422
|
+
* @param huffNode The array sorted by HUF_sort(). Builds the Huffman tree in this array.
|
|
423
|
+
* @param maxSymbolValue The maximum symbol value.
|
|
424
|
+
* @return The smallest node in the Huffman tree (by count).
|
|
425
|
+
*/
|
|
426
|
+
static int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue)
|
|
351
427
|
{
|
|
352
|
-
nodeElt* const huffNode0 =
|
|
353
|
-
|
|
354
|
-
U32 n, nonNullRank;
|
|
428
|
+
nodeElt* const huffNode0 = huffNode - 1;
|
|
429
|
+
int nonNullRank;
|
|
355
430
|
int lowS, lowN;
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
/* safety checks */
|
|
360
|
-
if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
361
|
-
if (wkspSize < sizeof(huffNodeTable)) return ERROR(workSpace_tooSmall);
|
|
362
|
-
if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
|
|
363
|
-
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
|
|
364
|
-
memset(huffNode0, 0, sizeof(huffNodeTable));
|
|
365
|
-
|
|
366
|
-
/* sort, decreasing order */
|
|
367
|
-
HUF_sort(huffNode, count, maxSymbolValue);
|
|
368
|
-
|
|
431
|
+
int nodeNb = STARTNODE;
|
|
432
|
+
int n, nodeRoot;
|
|
369
433
|
/* init for parents */
|
|
370
|
-
nonNullRank = maxSymbolValue;
|
|
434
|
+
nonNullRank = (int)maxSymbolValue;
|
|
371
435
|
while(huffNode[nonNullRank].count == 0) nonNullRank--;
|
|
372
436
|
lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;
|
|
373
437
|
huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;
|
|
374
|
-
huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb;
|
|
438
|
+
huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb;
|
|
375
439
|
nodeNb++; lowS-=2;
|
|
376
440
|
for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);
|
|
377
441
|
huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */
|
|
378
442
|
|
|
379
443
|
/* create parents */
|
|
380
444
|
while (nodeNb <= nodeRoot) {
|
|
381
|
-
|
|
382
|
-
|
|
445
|
+
int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
|
|
446
|
+
int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
|
|
383
447
|
huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count;
|
|
384
|
-
huffNode[n1].parent = huffNode[n2].parent = nodeNb;
|
|
448
|
+
huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb;
|
|
385
449
|
nodeNb++;
|
|
386
450
|
}
|
|
387
451
|
|
|
@@ -392,42 +456,73 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo
|
|
|
392
456
|
for (n=0; n<=nonNullRank; n++)
|
|
393
457
|
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;
|
|
394
458
|
|
|
395
|
-
|
|
396
|
-
maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits);
|
|
397
|
-
|
|
398
|
-
/* fill result into tree (val, nbBits) */
|
|
399
|
-
{ U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};
|
|
400
|
-
U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};
|
|
401
|
-
if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
|
|
402
|
-
for (n=0; n<=nonNullRank; n++)
|
|
403
|
-
nbPerRank[huffNode[n].nbBits]++;
|
|
404
|
-
/* determine stating value per rank */
|
|
405
|
-
{ U16 min = 0;
|
|
406
|
-
for (n=maxNbBits; n>0; n--) {
|
|
407
|
-
valPerRank[n] = min; /* get starting value within each rank */
|
|
408
|
-
min += nbPerRank[n];
|
|
409
|
-
min >>= 1;
|
|
410
|
-
} }
|
|
411
|
-
for (n=0; n<=maxSymbolValue; n++)
|
|
412
|
-
tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
|
|
413
|
-
for (n=0; n<=maxSymbolValue; n++)
|
|
414
|
-
tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
return maxNbBits;
|
|
459
|
+
return nonNullRank;
|
|
418
460
|
}
|
|
419
461
|
|
|
420
|
-
/**
|
|
421
|
-
*
|
|
422
|
-
*
|
|
462
|
+
/**
|
|
463
|
+
* HUF_buildCTableFromTree():
|
|
464
|
+
* Build the CTable given the Huffman tree in huffNode.
|
|
465
|
+
*
|
|
466
|
+
* @param[out] CTable The output Huffman CTable.
|
|
467
|
+
* @param huffNode The Huffman tree.
|
|
468
|
+
* @param nonNullRank The last and smallest node in the Huffman tree.
|
|
469
|
+
* @param maxSymbolValue The maximum symbol value.
|
|
470
|
+
* @param maxNbBits The exact maximum number of bits used in the Huffman tree.
|
|
423
471
|
*/
|
|
424
|
-
|
|
472
|
+
static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits)
|
|
425
473
|
{
|
|
426
|
-
|
|
427
|
-
|
|
474
|
+
/* fill result into ctable (val, nbBits) */
|
|
475
|
+
int n;
|
|
476
|
+
U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};
|
|
477
|
+
U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};
|
|
478
|
+
int const alphabetSize = (int)(maxSymbolValue + 1);
|
|
479
|
+
for (n=0; n<=nonNullRank; n++)
|
|
480
|
+
nbPerRank[huffNode[n].nbBits]++;
|
|
481
|
+
/* determine starting value per rank */
|
|
482
|
+
{ U16 min = 0;
|
|
483
|
+
for (n=(int)maxNbBits; n>0; n--) {
|
|
484
|
+
valPerRank[n] = min; /* get starting value within each rank */
|
|
485
|
+
min += nbPerRank[n];
|
|
486
|
+
min >>= 1;
|
|
487
|
+
} }
|
|
488
|
+
for (n=0; n<alphabetSize; n++)
|
|
489
|
+
CTable[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
|
|
490
|
+
for (n=0; n<alphabetSize; n++)
|
|
491
|
+
CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */
|
|
428
492
|
}
|
|
429
493
|
|
|
430
|
-
|
|
494
|
+
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
|
|
495
|
+
{
|
|
496
|
+
HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace;
|
|
497
|
+
nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;
|
|
498
|
+
nodeElt* const huffNode = huffNode0+1;
|
|
499
|
+
int nonNullRank;
|
|
500
|
+
|
|
501
|
+
/* safety checks */
|
|
502
|
+
if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
503
|
+
if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))
|
|
504
|
+
return ERROR(workSpace_tooSmall);
|
|
505
|
+
if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
|
|
506
|
+
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)
|
|
507
|
+
return ERROR(maxSymbolValue_tooLarge);
|
|
508
|
+
ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable));
|
|
509
|
+
|
|
510
|
+
/* sort, decreasing order */
|
|
511
|
+
HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition);
|
|
512
|
+
|
|
513
|
+
/* build tree */
|
|
514
|
+
nonNullRank = HUF_buildTree(huffNode, maxSymbolValue);
|
|
515
|
+
|
|
516
|
+
/* enforce maxTableLog */
|
|
517
|
+
maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits);
|
|
518
|
+
if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
|
|
519
|
+
|
|
520
|
+
HUF_buildCTableFromTree(tree, huffNode, nonNullRank, maxSymbolValue, maxNbBits);
|
|
521
|
+
|
|
522
|
+
return maxNbBits;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)
|
|
431
526
|
{
|
|
432
527
|
size_t nbBits = 0;
|
|
433
528
|
int s;
|
|
@@ -437,7 +532,7 @@ static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count
|
|
|
437
532
|
return nbBits >> 3;
|
|
438
533
|
}
|
|
439
534
|
|
|
440
|
-
|
|
535
|
+
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) {
|
|
441
536
|
int bad = 0;
|
|
442
537
|
int s;
|
|
443
538
|
for (s = 0; s <= (int)maxSymbolValue; ++s) {
|
|
@@ -476,7 +571,7 @@ HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
|
|
|
476
571
|
|
|
477
572
|
/* init */
|
|
478
573
|
if (dstSize < 8) return 0; /* not enough space to compress */
|
|
479
|
-
{ size_t const initErr = BIT_initCStream(&bitC, op, oend-op);
|
|
574
|
+
{ size_t const initErr = BIT_initCStream(&bitC, op, (size_t)(oend-op));
|
|
480
575
|
if (HUF_isError(initErr)) return 0; }
|
|
481
576
|
|
|
482
577
|
n = srcSize & ~3; /* join to mod 4 */
|
|
@@ -573,7 +668,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
|
|
573
668
|
if (srcSize < 12) return 0; /* no saving possible : too small input */
|
|
574
669
|
op += 6; /* jumpTable */
|
|
575
670
|
|
|
576
|
-
|
|
671
|
+
assert(op <= oend);
|
|
672
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
|
|
577
673
|
if (cSize==0) return 0;
|
|
578
674
|
assert(cSize <= 65535);
|
|
579
675
|
MEM_writeLE16(ostart, (U16)cSize);
|
|
@@ -581,7 +677,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
|
|
581
677
|
}
|
|
582
678
|
|
|
583
679
|
ip += segmentSize;
|
|
584
|
-
|
|
680
|
+
assert(op <= oend);
|
|
681
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
|
|
585
682
|
if (cSize==0) return 0;
|
|
586
683
|
assert(cSize <= 65535);
|
|
587
684
|
MEM_writeLE16(ostart+2, (U16)cSize);
|
|
@@ -589,7 +686,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
|
|
589
686
|
}
|
|
590
687
|
|
|
591
688
|
ip += segmentSize;
|
|
592
|
-
|
|
689
|
+
assert(op <= oend);
|
|
690
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
|
|
593
691
|
if (cSize==0) return 0;
|
|
594
692
|
assert(cSize <= 65535);
|
|
595
693
|
MEM_writeLE16(ostart+4, (U16)cSize);
|
|
@@ -597,12 +695,14 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
|
|
597
695
|
}
|
|
598
696
|
|
|
599
697
|
ip += segmentSize;
|
|
600
|
-
|
|
698
|
+
assert(op <= oend);
|
|
699
|
+
assert(ip <= iend);
|
|
700
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) );
|
|
601
701
|
if (cSize==0) return 0;
|
|
602
702
|
op += cSize;
|
|
603
703
|
}
|
|
604
704
|
|
|
605
|
-
return op-ostart;
|
|
705
|
+
return (size_t)(op-ostart);
|
|
606
706
|
}
|
|
607
707
|
|
|
608
708
|
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
|
|
@@ -618,40 +718,44 @@ static size_t HUF_compressCTable_internal(
|
|
|
618
718
|
HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2)
|
|
619
719
|
{
|
|
620
720
|
size_t const cSize = (nbStreams==HUF_singleStream) ?
|
|
621
|
-
HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) :
|
|
622
|
-
HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2);
|
|
721
|
+
HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2) :
|
|
722
|
+
HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2);
|
|
623
723
|
if (HUF_isError(cSize)) { return cSize; }
|
|
624
724
|
if (cSize==0) { return 0; } /* uncompressible */
|
|
625
725
|
op += cSize;
|
|
626
726
|
/* check compressibility */
|
|
727
|
+
assert(op >= ostart);
|
|
627
728
|
if ((size_t)(op-ostart) >= srcSize-1) { return 0; }
|
|
628
|
-
return op-ostart;
|
|
729
|
+
return (size_t)(op-ostart);
|
|
629
730
|
}
|
|
630
731
|
|
|
631
732
|
typedef struct {
|
|
632
733
|
unsigned count[HUF_SYMBOLVALUE_MAX + 1];
|
|
633
734
|
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
|
|
634
|
-
|
|
735
|
+
HUF_buildCTable_wksp_tables buildCTable_wksp;
|
|
635
736
|
} HUF_compress_tables_t;
|
|
636
737
|
|
|
637
738
|
/* HUF_compress_internal() :
|
|
638
|
-
* `
|
|
739
|
+
* `workSpace_align4` must be aligned on 4-bytes boundaries,
|
|
740
|
+
* and occupies the same space as a table of HUF_WORKSPACE_SIZE_U32 unsigned */
|
|
639
741
|
static size_t
|
|
640
742
|
HUF_compress_internal (void* dst, size_t dstSize,
|
|
641
743
|
const void* src, size_t srcSize,
|
|
642
744
|
unsigned maxSymbolValue, unsigned huffLog,
|
|
643
745
|
HUF_nbStreams_e nbStreams,
|
|
644
|
-
void*
|
|
746
|
+
void* workSpace_align4, size_t wkspSize,
|
|
645
747
|
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
|
|
646
748
|
const int bmi2)
|
|
647
749
|
{
|
|
648
|
-
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)
|
|
750
|
+
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace_align4;
|
|
649
751
|
BYTE* const ostart = (BYTE*)dst;
|
|
650
752
|
BYTE* const oend = ostart + dstSize;
|
|
651
753
|
BYTE* op = ostart;
|
|
652
754
|
|
|
755
|
+
HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE);
|
|
756
|
+
assert(((size_t)workSpace_align4 & 3) == 0); /* must be aligned on 4-bytes boundaries */
|
|
757
|
+
|
|
653
758
|
/* checks & inits */
|
|
654
|
-
if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
655
759
|
if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall);
|
|
656
760
|
if (!srcSize) return 0; /* Uncompressed */
|
|
657
761
|
if (!dstSize) return 0; /* cannot fit anything within dst budget */
|
|
@@ -669,7 +773,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
|
|
669
773
|
}
|
|
670
774
|
|
|
671
775
|
/* Scan input and build symbol stats */
|
|
672
|
-
{ CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize,
|
|
776
|
+
{ CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace_align4, wkspSize) );
|
|
673
777
|
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
|
|
674
778
|
if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */
|
|
675
779
|
}
|
|
@@ -691,11 +795,11 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
|
|
691
795
|
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
|
692
796
|
{ size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
|
|
693
797
|
maxSymbolValue, huffLog,
|
|
694
|
-
table->
|
|
798
|
+
&table->buildCTable_wksp, sizeof(table->buildCTable_wksp));
|
|
695
799
|
CHECK_F(maxBits);
|
|
696
800
|
huffLog = (U32)maxBits;
|
|
697
801
|
/* Zero unused symbols in CTable, so we can check it for validity */
|
|
698
|
-
|
|
802
|
+
ZSTD_memset(table->CTable + (maxSymbolValue + 1), 0,
|
|
699
803
|
sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));
|
|
700
804
|
}
|
|
701
805
|
|
|
@@ -716,7 +820,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
|
|
716
820
|
op += hSize;
|
|
717
821
|
if (repeat) { *repeat = HUF_repeat_none; }
|
|
718
822
|
if (oldHufTable)
|
|
719
|
-
|
|
823
|
+
ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */
|
|
720
824
|
}
|
|
721
825
|
return HUF_compressCTable_internal(ostart, op, oend,
|
|
722
826
|
src, srcSize,
|
|
@@ -747,14 +851,6 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
|
|
|
747
851
|
repeat, preferRepeat, bmi2);
|
|
748
852
|
}
|
|
749
853
|
|
|
750
|
-
size_t HUF_compress1X (void* dst, size_t dstSize,
|
|
751
|
-
const void* src, size_t srcSize,
|
|
752
|
-
unsigned maxSymbolValue, unsigned huffLog)
|
|
753
|
-
{
|
|
754
|
-
unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
|
|
755
|
-
return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
|
|
756
|
-
}
|
|
757
|
-
|
|
758
854
|
/* HUF_compress4X_repeat():
|
|
759
855
|
* compress input using 4 streams.
|
|
760
856
|
* provide workspace to generate compression tables */
|
|
@@ -784,6 +880,25 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
|
|
|
784
880
|
hufTable, repeat, preferRepeat, bmi2);
|
|
785
881
|
}
|
|
786
882
|
|
|
883
|
+
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
|
|
884
|
+
/** HUF_buildCTable() :
|
|
885
|
+
* @return : maxNbBits
|
|
886
|
+
* Note : count is used before tree is written, so they can safely overlap
|
|
887
|
+
*/
|
|
888
|
+
size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)
|
|
889
|
+
{
|
|
890
|
+
HUF_buildCTable_wksp_tables workspace;
|
|
891
|
+
return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace));
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
size_t HUF_compress1X (void* dst, size_t dstSize,
|
|
895
|
+
const void* src, size_t srcSize,
|
|
896
|
+
unsigned maxSymbolValue, unsigned huffLog)
|
|
897
|
+
{
|
|
898
|
+
unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
|
|
899
|
+
return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
|
|
900
|
+
}
|
|
901
|
+
|
|
787
902
|
size_t HUF_compress2 (void* dst, size_t dstSize,
|
|
788
903
|
const void* src, size_t srcSize,
|
|
789
904
|
unsigned maxSymbolValue, unsigned huffLog)
|
|
@@ -796,3 +911,4 @@ size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSi
|
|
|
796
911
|
{
|
|
797
912
|
return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);
|
|
798
913
|
}
|
|
914
|
+
#endif
|