extzstd 0.1.1 → 0.2
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 +5 -5
- data/HISTORY.ja.md +18 -0
- data/README.md +15 -50
- data/contrib/zstd/CONTRIBUTING.md +1 -1
- data/contrib/zstd/COPYING +339 -0
- data/contrib/zstd/Makefile +82 -51
- data/contrib/zstd/NEWS +92 -5
- data/contrib/zstd/README.md +50 -41
- data/contrib/zstd/appveyor.yml +164 -102
- data/contrib/zstd/circle.yml +10 -22
- data/contrib/zstd/lib/BUCK +31 -10
- data/contrib/zstd/lib/Makefile +57 -31
- data/contrib/zstd/lib/README.md +68 -37
- data/contrib/zstd/lib/common/bitstream.h +130 -76
- data/contrib/zstd/lib/common/compiler.h +86 -0
- data/contrib/zstd/lib/common/error_private.c +15 -11
- data/contrib/zstd/lib/common/error_private.h +8 -8
- data/contrib/zstd/lib/common/fse.h +19 -9
- data/contrib/zstd/lib/common/fse_decompress.c +3 -22
- data/contrib/zstd/lib/common/huf.h +68 -26
- data/contrib/zstd/lib/common/mem.h +23 -35
- data/contrib/zstd/lib/common/pool.c +123 -63
- data/contrib/zstd/lib/common/pool.h +19 -10
- data/contrib/zstd/lib/common/threading.c +11 -16
- data/contrib/zstd/lib/common/threading.h +52 -33
- data/contrib/zstd/lib/common/xxhash.c +28 -22
- data/contrib/zstd/lib/common/zstd_common.c +40 -27
- data/contrib/zstd/lib/common/zstd_errors.h +43 -34
- data/contrib/zstd/lib/common/zstd_internal.h +131 -123
- data/contrib/zstd/lib/compress/fse_compress.c +17 -33
- data/contrib/zstd/lib/compress/huf_compress.c +15 -9
- data/contrib/zstd/lib/compress/zstd_compress.c +2096 -2363
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +462 -0
- data/contrib/zstd/lib/compress/zstd_double_fast.c +309 -0
- data/contrib/zstd/lib/compress/zstd_double_fast.h +29 -0
- data/contrib/zstd/lib/compress/zstd_fast.c +243 -0
- data/contrib/zstd/lib/compress/zstd_fast.h +31 -0
- data/contrib/zstd/lib/compress/zstd_lazy.c +765 -0
- data/contrib/zstd/lib/compress/zstd_lazy.h +39 -0
- data/contrib/zstd/lib/compress/zstd_ldm.c +707 -0
- data/contrib/zstd/lib/compress/zstd_ldm.h +68 -0
- data/contrib/zstd/lib/compress/zstd_opt.c +785 -0
- data/contrib/zstd/lib/compress/zstd_opt.h +19 -908
- data/contrib/zstd/lib/compress/zstdmt_compress.c +737 -327
- data/contrib/zstd/lib/compress/zstdmt_compress.h +88 -26
- data/contrib/zstd/lib/decompress/huf_decompress.c +158 -50
- data/contrib/zstd/lib/decompress/zstd_decompress.c +884 -699
- data/contrib/zstd/lib/deprecated/zbuff.h +5 -4
- data/contrib/zstd/lib/deprecated/zbuff_common.c +5 -5
- data/contrib/zstd/lib/deprecated/zbuff_compress.c +6 -4
- data/contrib/zstd/lib/deprecated/zbuff_decompress.c +5 -4
- data/contrib/zstd/lib/dictBuilder/cover.c +93 -77
- data/contrib/zstd/lib/dictBuilder/zdict.c +107 -92
- data/contrib/zstd/lib/dictBuilder/zdict.h +112 -102
- data/contrib/zstd/lib/legacy/zstd_legacy.h +9 -4
- data/contrib/zstd/lib/legacy/zstd_v01.c +7 -6
- data/contrib/zstd/lib/legacy/zstd_v01.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v02.c +27 -99
- data/contrib/zstd/lib/legacy/zstd_v02.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v03.c +26 -98
- data/contrib/zstd/lib/legacy/zstd_v03.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v04.c +22 -91
- data/contrib/zstd/lib/legacy/zstd_v04.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v05.c +23 -99
- data/contrib/zstd/lib/legacy/zstd_v05.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v06.c +22 -96
- data/contrib/zstd/lib/legacy/zstd_v06.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v07.c +19 -95
- data/contrib/zstd/lib/legacy/zstd_v07.h +5 -4
- data/contrib/zstd/lib/zstd.h +895 -271
- data/ext/extconf.rb +11 -2
- data/ext/extzstd.c +45 -128
- data/ext/extzstd.h +74 -31
- data/ext/extzstd_stream.c +401 -142
- data/ext/zstd_common.c +5 -0
- data/ext/zstd_compress.c +8 -0
- data/ext/zstd_decompress.c +1 -0
- data/ext/zstd_dictbuilder.c +2 -0
- data/lib/extzstd/version.rb +1 -1
- data/lib/extzstd.rb +48 -1
- data/test/test_basic.rb +9 -1
- metadata +17 -7
- data/HISTORY.ja +0 -10
- data/contrib/zstd/LICENSE-examples +0 -11
- data/contrib/zstd/PATENTS +0 -33
data/contrib/zstd/lib/README.md
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
Zstandard library files
|
|
2
2
|
================================
|
|
3
3
|
|
|
4
|
-
The __lib__ directory
|
|
5
|
-
|
|
4
|
+
The __lib__ directory is split into several sub-directories,
|
|
5
|
+
in order to make it easier to select or exclude specific features.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
#### Building
|
|
9
|
+
|
|
10
|
+
`Makefile` script is provided, supporting the standard set of commands,
|
|
11
|
+
directories, and variables (see https://www.gnu.org/prep/standards/html_node/Command-Variables.html).
|
|
12
|
+
- `make` : generates both static and dynamic libraries
|
|
13
|
+
- `make install` : install libraries in default system directories
|
|
6
14
|
|
|
7
15
|
|
|
8
16
|
#### API
|
|
9
17
|
|
|
10
|
-
Zstandard's stable API is exposed within [zstd.h](zstd.h)
|
|
11
|
-
at the root of `lib` directory.
|
|
18
|
+
Zstandard's stable API is exposed within [lib/zstd.h](zstd.h).
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
#### Advanced API
|
|
15
22
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
Optional advanced features are exposed via :
|
|
24
|
+
|
|
25
|
+
- `lib/common/zstd_errors.h` : translates `size_t` function results
|
|
26
|
+
into an `ZSTD_ErrorCode`, for accurate error handling.
|
|
27
|
+
- `ZSTD_STATIC_LINKING_ONLY` : if this macro is defined _before_ including `zstd.h`,
|
|
28
|
+
it unlocks access to advanced experimental API,
|
|
29
|
+
exposed in second part of `zstd.h`.
|
|
21
30
|
These APIs shall ___never be used with dynamic library___ !
|
|
22
31
|
They are not "stable", their definition may change in the future.
|
|
23
32
|
Only static linking is allowed.
|
|
@@ -25,25 +34,45 @@ Some additional API may be useful if you're looking into advanced features :
|
|
|
25
34
|
|
|
26
35
|
#### Modular build
|
|
27
36
|
|
|
28
|
-
Directory `common
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
The
|
|
42
|
-
|
|
43
|
-
For example, advanced API for version `v0.4` is in `legacy/zstd_v04.h` .
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
####
|
|
37
|
+
- Directory `lib/common` is always required, for all variants.
|
|
38
|
+
- Compression source code lies in `lib/compress`
|
|
39
|
+
- Decompression source code lies in `lib/decompress`
|
|
40
|
+
- It's possible to include only `compress` or only `decompress`, they don't depend on each other.
|
|
41
|
+
- `lib/dictBuilder` : makes it possible to generate dictionaries from a set of samples.
|
|
42
|
+
The API is exposed in `lib/dictBuilder/zdict.h`.
|
|
43
|
+
This module depends on both `lib/common` and `lib/compress` .
|
|
44
|
+
- `lib/legacy` : source code to decompress older zstd formats, starting from `v0.1`.
|
|
45
|
+
This module depends on `lib/common` and `lib/decompress`.
|
|
46
|
+
To enable this feature, it's necessary to define `ZSTD_LEGACY_SUPPORT = 1` during compilation.
|
|
47
|
+
Typically, with `gcc`, add argument `-DZSTD_LEGACY_SUPPORT=1`.
|
|
48
|
+
Using higher number limits the number of version supported.
|
|
49
|
+
For example, `ZSTD_LEGACY_SUPPORT=2` means : "support legacy formats starting from v0.2+".
|
|
50
|
+
The API is exposed in `lib/legacy/zstd_legacy.h`.
|
|
51
|
+
Each version also provides a (dedicated) set of advanced API.
|
|
52
|
+
For example, advanced API for version `v0.4` is exposed in `lib/legacy/zstd_v04.h` .
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
#### Multithreading support
|
|
56
|
+
|
|
57
|
+
Multithreading is disabled by default when building with `make`.
|
|
58
|
+
Enabling multithreading requires 2 conditions :
|
|
59
|
+
- set macro `ZSTD_MULTITHREAD`
|
|
60
|
+
- on POSIX systems : compile with pthread (`-pthread` compilation flag for `gcc` for example)
|
|
61
|
+
|
|
62
|
+
Both conditions are automatically triggered by invoking `make lib-mt` target.
|
|
63
|
+
Note that, when linking a POSIX program with a multithreaded version of `libzstd`,
|
|
64
|
+
it's necessary to trigger `-pthread` flag during link stage.
|
|
65
|
+
|
|
66
|
+
Multithreading capabilities are exposed via :
|
|
67
|
+
- private API `lib/compress/zstdmt_compress.h`.
|
|
68
|
+
Symbols defined in this header are currently exposed in `libzstd`, hence usable.
|
|
69
|
+
Note however that this API is planned to be locked and remain strictly internal in the future.
|
|
70
|
+
- advanced API `ZSTD_compress_generic()`, defined in `lib/zstd.h`, experimental section.
|
|
71
|
+
This API is still considered experimental, but is designed to be labelled "stable" at some point in the future.
|
|
72
|
+
It's the recommended entry point for multi-threading operations.
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#### Windows : using MinGW+MSYS to create DLL
|
|
47
76
|
|
|
48
77
|
DLL can be created using MinGW+MSYS with the `make libzstd` command.
|
|
49
78
|
This command creates `dll\libzstd.dll` and the import library `dll\libzstd.lib`.
|
|
@@ -59,19 +88,21 @@ file it should be linked with `dll\libzstd.dll`. For example:
|
|
|
59
88
|
The compiled executable will require ZSTD DLL which is available at `dll\libzstd.dll`.
|
|
60
89
|
|
|
61
90
|
|
|
62
|
-
####
|
|
91
|
+
#### Deprecated API
|
|
63
92
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
93
|
+
Obsolete API on their way out are stored in directory `lib/deprecated`.
|
|
94
|
+
At this stage, it contains older streaming prototypes, in `lib/deprecated/zbuff.h`.
|
|
95
|
+
Presence in this directory is temporary.
|
|
96
|
+
These prototypes will be removed in some future version.
|
|
97
|
+
Consider migrating code towards supported streaming API exposed in `zstd.h`.
|
|
68
98
|
|
|
69
99
|
|
|
70
100
|
#### Miscellaneous
|
|
71
101
|
|
|
72
102
|
The other files are not source code. There are :
|
|
73
103
|
|
|
74
|
-
- LICENSE : contains the BSD license text
|
|
75
|
-
- Makefile : script to
|
|
76
|
-
-
|
|
77
|
-
-
|
|
104
|
+
- `LICENSE` : contains the BSD license text
|
|
105
|
+
- `Makefile` : `make` script to build and install zstd library (static and dynamic)
|
|
106
|
+
- `BUCK` : support for `buck` build system (https://buckbuild.com/)
|
|
107
|
+
- `libzstd.pc.in` : for `pkg-config` (used in `make install`)
|
|
108
|
+
- `README.md` : this file
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
bitstream
|
|
3
3
|
Part of FSE library
|
|
4
4
|
header file (to include)
|
|
5
|
-
Copyright (C) 2013-
|
|
5
|
+
Copyright (C) 2013-2017, Yann Collet.
|
|
6
6
|
|
|
7
7
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
|
8
8
|
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
extern "C" {
|
|
40
40
|
#endif
|
|
41
41
|
|
|
42
|
-
|
|
43
42
|
/*
|
|
44
43
|
* This API consists of small unitary functions, which must be inlined for best performance.
|
|
45
44
|
* Since link-time-optimization is not available for all compilers,
|
|
@@ -53,6 +52,18 @@ extern "C" {
|
|
|
53
52
|
#include "error_private.h" /* error codes and messages */
|
|
54
53
|
|
|
55
54
|
|
|
55
|
+
/*-*************************************
|
|
56
|
+
* Debug
|
|
57
|
+
***************************************/
|
|
58
|
+
#if defined(BIT_DEBUG) && (BIT_DEBUG>=1)
|
|
59
|
+
# include <assert.h>
|
|
60
|
+
#else
|
|
61
|
+
# ifndef assert
|
|
62
|
+
# define assert(condition) ((void)0)
|
|
63
|
+
# endif
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
|
|
56
67
|
/*=========================================
|
|
57
68
|
* Target specific
|
|
58
69
|
=========================================*/
|
|
@@ -64,17 +75,18 @@ extern "C" {
|
|
|
64
75
|
#define STREAM_ACCUMULATOR_MIN_64 57
|
|
65
76
|
#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
|
|
66
77
|
|
|
78
|
+
|
|
67
79
|
/*-******************************************
|
|
68
80
|
* bitStream encoding API (write forward)
|
|
69
81
|
********************************************/
|
|
70
82
|
/* bitStream can mix input from multiple sources.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*/
|
|
83
|
+
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
|
84
|
+
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
|
85
|
+
*/
|
|
74
86
|
typedef struct
|
|
75
87
|
{
|
|
76
88
|
size_t bitContainer;
|
|
77
|
-
|
|
89
|
+
unsigned bitPos;
|
|
78
90
|
char* startPtr;
|
|
79
91
|
char* ptr;
|
|
80
92
|
char* endPtr;
|
|
@@ -112,6 +124,7 @@ typedef struct
|
|
|
112
124
|
unsigned bitsConsumed;
|
|
113
125
|
const char* ptr;
|
|
114
126
|
const char* start;
|
|
127
|
+
const char* limitPtr;
|
|
115
128
|
} BIT_DStream_t;
|
|
116
129
|
|
|
117
130
|
typedef enum { BIT_DStream_unfinished = 0,
|
|
@@ -154,140 +167,178 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
|
|
154
167
|
/*-**************************************************************
|
|
155
168
|
* Internal functions
|
|
156
169
|
****************************************************************/
|
|
157
|
-
MEM_STATIC unsigned BIT_highbit32 (
|
|
170
|
+
MEM_STATIC unsigned BIT_highbit32 (U32 val)
|
|
158
171
|
{
|
|
172
|
+
assert(val != 0);
|
|
173
|
+
{
|
|
159
174
|
# if defined(_MSC_VER) /* Visual */
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
175
|
+
unsigned long r=0;
|
|
176
|
+
_BitScanReverse ( &r, val );
|
|
177
|
+
return (unsigned) r;
|
|
163
178
|
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
|
164
|
-
|
|
179
|
+
return 31 - __builtin_clz (val);
|
|
165
180
|
# else /* Software version */
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
181
|
+
static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
|
|
182
|
+
11, 14, 16, 18, 22, 25, 3, 30,
|
|
183
|
+
8, 12, 20, 28, 15, 17, 24, 7,
|
|
184
|
+
19, 27, 23, 6, 26, 5, 4, 31 };
|
|
185
|
+
U32 v = val;
|
|
186
|
+
v |= v >> 1;
|
|
187
|
+
v |= v >> 2;
|
|
188
|
+
v |= v >> 4;
|
|
189
|
+
v |= v >> 8;
|
|
190
|
+
v |= v >> 16;
|
|
191
|
+
return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
|
|
174
192
|
# endif
|
|
193
|
+
}
|
|
175
194
|
}
|
|
176
195
|
|
|
177
196
|
/*===== Local Constants =====*/
|
|
178
|
-
static const unsigned BIT_mask[] = {
|
|
179
|
-
|
|
197
|
+
static const unsigned BIT_mask[] = {
|
|
198
|
+
0, 1, 3, 7, 0xF, 0x1F,
|
|
199
|
+
0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
|
|
200
|
+
0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
|
|
201
|
+
0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
|
|
202
|
+
0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
|
|
203
|
+
0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
|
|
204
|
+
#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
|
|
180
205
|
|
|
181
206
|
/*-**************************************************************
|
|
182
207
|
* bitStream encoding
|
|
183
208
|
****************************************************************/
|
|
184
209
|
/*! BIT_initCStream() :
|
|
185
|
-
* `dstCapacity` must be > sizeof(
|
|
210
|
+
* `dstCapacity` must be > sizeof(size_t)
|
|
186
211
|
* @return : 0 if success,
|
|
187
|
-
|
|
188
|
-
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
|
|
212
|
+
* otherwise an error code (can be tested using ERR_isError()) */
|
|
213
|
+
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
|
|
214
|
+
void* startPtr, size_t dstCapacity)
|
|
189
215
|
{
|
|
190
216
|
bitC->bitContainer = 0;
|
|
191
217
|
bitC->bitPos = 0;
|
|
192
218
|
bitC->startPtr = (char*)startPtr;
|
|
193
219
|
bitC->ptr = bitC->startPtr;
|
|
194
|
-
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->
|
|
195
|
-
if (dstCapacity <= sizeof(bitC->
|
|
220
|
+
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
|
|
221
|
+
if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
|
|
196
222
|
return 0;
|
|
197
223
|
}
|
|
198
224
|
|
|
199
225
|
/*! BIT_addBits() :
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
|
|
226
|
+
* can add up to 31 bits into `bitC`.
|
|
227
|
+
* Note : does not check for register overflow ! */
|
|
228
|
+
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
|
|
229
|
+
size_t value, unsigned nbBits)
|
|
203
230
|
{
|
|
231
|
+
MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32);
|
|
232
|
+
assert(nbBits < BIT_MASK_SIZE);
|
|
233
|
+
assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
|
204
234
|
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
|
|
205
235
|
bitC->bitPos += nbBits;
|
|
206
236
|
}
|
|
207
237
|
|
|
208
238
|
/*! BIT_addBitsFast() :
|
|
209
239
|
* works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
|
|
210
|
-
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
|
|
240
|
+
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
|
|
241
|
+
size_t value, unsigned nbBits)
|
|
211
242
|
{
|
|
243
|
+
assert((value>>nbBits) == 0);
|
|
244
|
+
assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
|
212
245
|
bitC->bitContainer |= value << bitC->bitPos;
|
|
213
246
|
bitC->bitPos += nbBits;
|
|
214
247
|
}
|
|
215
248
|
|
|
216
249
|
/*! BIT_flushBitsFast() :
|
|
250
|
+
* assumption : bitContainer has not overflowed
|
|
217
251
|
* unsafe version; does not check buffer overflow */
|
|
218
252
|
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
|
219
253
|
{
|
|
220
254
|
size_t const nbBytes = bitC->bitPos >> 3;
|
|
255
|
+
assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
|
221
256
|
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
|
222
257
|
bitC->ptr += nbBytes;
|
|
258
|
+
assert(bitC->ptr <= bitC->endPtr);
|
|
223
259
|
bitC->bitPos &= 7;
|
|
224
|
-
bitC->bitContainer >>= nbBytes*8;
|
|
260
|
+
bitC->bitContainer >>= nbBytes*8;
|
|
225
261
|
}
|
|
226
262
|
|
|
227
263
|
/*! BIT_flushBits() :
|
|
264
|
+
* assumption : bitContainer has not overflowed
|
|
228
265
|
* safe version; check for buffer overflow, and prevents it.
|
|
229
|
-
* note : does not signal buffer overflow.
|
|
266
|
+
* note : does not signal buffer overflow.
|
|
267
|
+
* overflow will be revealed later on using BIT_closeCStream() */
|
|
230
268
|
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
|
231
269
|
{
|
|
232
270
|
size_t const nbBytes = bitC->bitPos >> 3;
|
|
271
|
+
assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
|
|
233
272
|
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
|
234
273
|
bitC->ptr += nbBytes;
|
|
235
274
|
if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
|
|
236
275
|
bitC->bitPos &= 7;
|
|
237
|
-
bitC->bitContainer >>= nbBytes*8;
|
|
276
|
+
bitC->bitContainer >>= nbBytes*8;
|
|
238
277
|
}
|
|
239
278
|
|
|
240
279
|
/*! BIT_closeCStream() :
|
|
241
280
|
* @return : size of CStream, in bytes,
|
|
242
|
-
|
|
281
|
+
* or 0 if it could not fit into dstBuffer */
|
|
243
282
|
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
|
|
244
283
|
{
|
|
245
284
|
BIT_addBitsFast(bitC, 1, 1); /* endMark */
|
|
246
285
|
BIT_flushBits(bitC);
|
|
247
|
-
|
|
248
|
-
if (bitC->ptr >= bitC->endPtr) return 0; /* doesn't fit within authorized budget : cancel */
|
|
249
|
-
|
|
286
|
+
if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
|
|
250
287
|
return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
|
|
251
288
|
}
|
|
252
289
|
|
|
253
290
|
|
|
254
291
|
/*-********************************************************
|
|
255
|
-
*
|
|
292
|
+
* bitStream decoding
|
|
256
293
|
**********************************************************/
|
|
257
294
|
/*! BIT_initDStream() :
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*/
|
|
295
|
+
* Initialize a BIT_DStream_t.
|
|
296
|
+
* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
|
|
297
|
+
* `srcSize` must be the *exact* size of the bitStream, in bytes.
|
|
298
|
+
* @return : size of stream (== srcSize), or an errorCode if a problem is detected
|
|
299
|
+
*/
|
|
263
300
|
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
|
|
264
301
|
{
|
|
265
302
|
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
|
266
303
|
|
|
304
|
+
bitD->start = (const char*)srcBuffer;
|
|
305
|
+
bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
|
|
306
|
+
|
|
267
307
|
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
|
|
268
|
-
bitD->start = (const char*)srcBuffer;
|
|
269
308
|
bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
|
|
270
309
|
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
|
271
310
|
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
|
272
311
|
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
|
|
273
312
|
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
|
274
313
|
} else {
|
|
275
|
-
bitD->start = (const char*)srcBuffer;
|
|
276
314
|
bitD->ptr = bitD->start;
|
|
277
315
|
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
|
278
316
|
switch(srcSize)
|
|
279
317
|
{
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
318
|
+
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
|
|
319
|
+
/* fall-through */
|
|
320
|
+
|
|
321
|
+
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
|
|
322
|
+
/* fall-through */
|
|
323
|
+
|
|
324
|
+
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
|
|
325
|
+
/* fall-through */
|
|
326
|
+
|
|
327
|
+
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
|
|
328
|
+
/* fall-through */
|
|
329
|
+
|
|
330
|
+
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
|
|
331
|
+
/* fall-through */
|
|
332
|
+
|
|
333
|
+
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
|
|
334
|
+
/* fall-through */
|
|
335
|
+
|
|
336
|
+
default: break;
|
|
337
|
+
}
|
|
338
|
+
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
|
339
|
+
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
|
|
340
|
+
if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */
|
|
287
341
|
}
|
|
288
|
-
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
|
289
|
-
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
|
|
290
|
-
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
|
291
342
|
bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
|
|
292
343
|
}
|
|
293
344
|
|
|
@@ -309,12 +360,14 @@ MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 co
|
|
|
309
360
|
# endif
|
|
310
361
|
return _bextr_u32(bitContainer, start, nbBits);
|
|
311
362
|
#else
|
|
363
|
+
assert(nbBits < BIT_MASK_SIZE);
|
|
312
364
|
return (bitContainer >> start) & BIT_mask[nbBits];
|
|
313
365
|
#endif
|
|
314
366
|
}
|
|
315
367
|
|
|
316
368
|
MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
|
317
369
|
{
|
|
370
|
+
assert(nbBits < BIT_MASK_SIZE);
|
|
318
371
|
return bitContainer & BIT_mask[nbBits];
|
|
319
372
|
}
|
|
320
373
|
|
|
@@ -323,24 +376,24 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
|
|
323
376
|
* local register is not modified.
|
|
324
377
|
* On 32-bits, maxNbBits==24.
|
|
325
378
|
* On 64-bits, maxNbBits==56.
|
|
326
|
-
*
|
|
327
|
-
|
|
328
|
-
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
|
379
|
+
* @return : value extracted */
|
|
380
|
+
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
|
329
381
|
{
|
|
330
382
|
#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
|
|
331
383
|
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
|
|
332
384
|
#else
|
|
333
|
-
U32 const
|
|
334
|
-
return ((bitD->bitContainer << (bitD->bitsConsumed &
|
|
385
|
+
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
|
386
|
+
return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
|
|
335
387
|
#endif
|
|
336
388
|
}
|
|
337
389
|
|
|
338
390
|
/*! BIT_lookBitsFast() :
|
|
339
|
-
*
|
|
391
|
+
* unsafe version; only works if nbBits >= 1 */
|
|
340
392
|
MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
|
|
341
393
|
{
|
|
342
|
-
U32 const
|
|
343
|
-
|
|
394
|
+
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
|
395
|
+
assert(nbBits >= 1);
|
|
396
|
+
return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
|
|
344
397
|
}
|
|
345
398
|
|
|
346
399
|
MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
|
@@ -351,8 +404,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
|
|
351
404
|
/*! BIT_readBits() :
|
|
352
405
|
* Read (consume) next n bits from local register and update.
|
|
353
406
|
* Pay attention to not read more than nbBits contained into local register.
|
|
354
|
-
*
|
|
355
|
-
*/
|
|
407
|
+
* @return : extracted value. */
|
|
356
408
|
MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
|
357
409
|
{
|
|
358
410
|
size_t const value = BIT_lookBits(bitD, nbBits);
|
|
@@ -361,25 +413,26 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
|
|
361
413
|
}
|
|
362
414
|
|
|
363
415
|
/*! BIT_readBitsFast() :
|
|
364
|
-
*
|
|
416
|
+
* unsafe version; only works only if nbBits >= 1 */
|
|
365
417
|
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
|
366
418
|
{
|
|
367
419
|
size_t const value = BIT_lookBitsFast(bitD, nbBits);
|
|
420
|
+
assert(nbBits >= 1);
|
|
368
421
|
BIT_skipBits(bitD, nbBits);
|
|
369
422
|
return value;
|
|
370
423
|
}
|
|
371
424
|
|
|
372
425
|
/*! BIT_reloadDStream() :
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
|
|
426
|
+
* Refill `bitD` from buffer previously set in BIT_initDStream() .
|
|
427
|
+
* This function is safe, it guarantees it will not read beyond src buffer.
|
|
428
|
+
* @return : status of `BIT_DStream_t` internal register.
|
|
429
|
+
* when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
|
|
377
430
|
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
|
378
431
|
{
|
|
379
|
-
|
|
380
|
-
|
|
432
|
+
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
|
|
433
|
+
return BIT_DStream_overflow;
|
|
381
434
|
|
|
382
|
-
if (bitD->ptr >= bitD->
|
|
435
|
+
if (bitD->ptr >= bitD->limitPtr) {
|
|
383
436
|
bitD->ptr -= bitD->bitsConsumed >> 3;
|
|
384
437
|
bitD->bitsConsumed &= 7;
|
|
385
438
|
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
|
@@ -389,6 +442,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
|
|
389
442
|
if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
|
|
390
443
|
return BIT_DStream_completed;
|
|
391
444
|
}
|
|
445
|
+
/* start < ptr < limitPtr */
|
|
392
446
|
{ U32 nbBytes = bitD->bitsConsumed >> 3;
|
|
393
447
|
BIT_DStream_status result = BIT_DStream_unfinished;
|
|
394
448
|
if (bitD->ptr - nbBytes < bitD->start) {
|
|
@@ -397,14 +451,14 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
|
|
397
451
|
}
|
|
398
452
|
bitD->ptr -= nbBytes;
|
|
399
453
|
bitD->bitsConsumed -= nbBytes*8;
|
|
400
|
-
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
|
|
454
|
+
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
|
|
401
455
|
return result;
|
|
402
456
|
}
|
|
403
457
|
}
|
|
404
458
|
|
|
405
459
|
/*! BIT_endOfDStream() :
|
|
406
|
-
*
|
|
407
|
-
*/
|
|
460
|
+
* @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
|
|
461
|
+
*/
|
|
408
462
|
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
|
409
463
|
{
|
|
410
464
|
return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2016-present, 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_COMPILER_H
|
|
12
|
+
#define ZSTD_COMPILER_H
|
|
13
|
+
|
|
14
|
+
/*-*******************************************************
|
|
15
|
+
* Compiler specifics
|
|
16
|
+
*********************************************************/
|
|
17
|
+
/* force inlining */
|
|
18
|
+
#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
|
19
|
+
# define INLINE_KEYWORD inline
|
|
20
|
+
#else
|
|
21
|
+
# define INLINE_KEYWORD
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
#if defined(__GNUC__)
|
|
25
|
+
# define FORCE_INLINE_ATTR __attribute__((always_inline))
|
|
26
|
+
#elif defined(_MSC_VER)
|
|
27
|
+
# define FORCE_INLINE_ATTR __forceinline
|
|
28
|
+
#else
|
|
29
|
+
# define FORCE_INLINE_ATTR
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
|
|
34
|
+
* parameters. They must be inlined for the compiler to elimininate the constant
|
|
35
|
+
* branches.
|
|
36
|
+
*/
|
|
37
|
+
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
|
38
|
+
/**
|
|
39
|
+
* HINT_INLINE is used to help the compiler generate better code. It is *not*
|
|
40
|
+
* used for "templates", so it can be tweaked based on the compilers
|
|
41
|
+
* performance.
|
|
42
|
+
*
|
|
43
|
+
* gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the
|
|
44
|
+
* always_inline attribute.
|
|
45
|
+
*
|
|
46
|
+
* clang up to 5.0.0 (trunk) benefit tremendously from the always_inline
|
|
47
|
+
* attribute.
|
|
48
|
+
*/
|
|
49
|
+
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
|
|
50
|
+
# define HINT_INLINE static INLINE_KEYWORD
|
|
51
|
+
#else
|
|
52
|
+
# define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
/* force no inlining */
|
|
56
|
+
#ifdef _MSC_VER
|
|
57
|
+
# define FORCE_NOINLINE static __declspec(noinline)
|
|
58
|
+
#else
|
|
59
|
+
# ifdef __GNUC__
|
|
60
|
+
# define FORCE_NOINLINE static __attribute__((__noinline__))
|
|
61
|
+
# else
|
|
62
|
+
# define FORCE_NOINLINE static
|
|
63
|
+
# endif
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
/* prefetch */
|
|
67
|
+
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
|
|
68
|
+
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
|
|
69
|
+
# define PREFETCH(ptr) _mm_prefetch((const char*)ptr, _MM_HINT_T0)
|
|
70
|
+
#elif defined(__GNUC__)
|
|
71
|
+
# define PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
|
|
72
|
+
#else
|
|
73
|
+
# define PREFETCH(ptr) /* disabled */
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
/* disable warnings */
|
|
77
|
+
#ifdef _MSC_VER /* Visual Studio */
|
|
78
|
+
# include <intrin.h> /* For Visual 2005 */
|
|
79
|
+
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
|
|
80
|
+
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
|
81
|
+
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
|
82
|
+
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
|
|
83
|
+
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
|
|
84
|
+
#endif
|
|
85
|
+
|
|
86
|
+
#endif /* ZSTD_COMPILER_H */
|