extzstd 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.ja.md +18 -0
  3. data/README.md +15 -50
  4. data/contrib/zstd/CONTRIBUTING.md +1 -1
  5. data/contrib/zstd/COPYING +339 -0
  6. data/contrib/zstd/Makefile +82 -51
  7. data/contrib/zstd/NEWS +92 -5
  8. data/contrib/zstd/README.md +50 -41
  9. data/contrib/zstd/appveyor.yml +164 -102
  10. data/contrib/zstd/circle.yml +10 -22
  11. data/contrib/zstd/lib/BUCK +31 -10
  12. data/contrib/zstd/lib/Makefile +57 -31
  13. data/contrib/zstd/lib/README.md +68 -37
  14. data/contrib/zstd/lib/common/bitstream.h +130 -76
  15. data/contrib/zstd/lib/common/compiler.h +86 -0
  16. data/contrib/zstd/lib/common/error_private.c +15 -11
  17. data/contrib/zstd/lib/common/error_private.h +8 -8
  18. data/contrib/zstd/lib/common/fse.h +19 -9
  19. data/contrib/zstd/lib/common/fse_decompress.c +3 -22
  20. data/contrib/zstd/lib/common/huf.h +68 -26
  21. data/contrib/zstd/lib/common/mem.h +23 -35
  22. data/contrib/zstd/lib/common/pool.c +123 -63
  23. data/contrib/zstd/lib/common/pool.h +19 -10
  24. data/contrib/zstd/lib/common/threading.c +11 -16
  25. data/contrib/zstd/lib/common/threading.h +52 -33
  26. data/contrib/zstd/lib/common/xxhash.c +28 -22
  27. data/contrib/zstd/lib/common/zstd_common.c +40 -27
  28. data/contrib/zstd/lib/common/zstd_errors.h +43 -34
  29. data/contrib/zstd/lib/common/zstd_internal.h +131 -123
  30. data/contrib/zstd/lib/compress/fse_compress.c +17 -33
  31. data/contrib/zstd/lib/compress/huf_compress.c +15 -9
  32. data/contrib/zstd/lib/compress/zstd_compress.c +2096 -2363
  33. data/contrib/zstd/lib/compress/zstd_compress_internal.h +462 -0
  34. data/contrib/zstd/lib/compress/zstd_double_fast.c +309 -0
  35. data/contrib/zstd/lib/compress/zstd_double_fast.h +29 -0
  36. data/contrib/zstd/lib/compress/zstd_fast.c +243 -0
  37. data/contrib/zstd/lib/compress/zstd_fast.h +31 -0
  38. data/contrib/zstd/lib/compress/zstd_lazy.c +765 -0
  39. data/contrib/zstd/lib/compress/zstd_lazy.h +39 -0
  40. data/contrib/zstd/lib/compress/zstd_ldm.c +707 -0
  41. data/contrib/zstd/lib/compress/zstd_ldm.h +68 -0
  42. data/contrib/zstd/lib/compress/zstd_opt.c +785 -0
  43. data/contrib/zstd/lib/compress/zstd_opt.h +19 -908
  44. data/contrib/zstd/lib/compress/zstdmt_compress.c +737 -327
  45. data/contrib/zstd/lib/compress/zstdmt_compress.h +88 -26
  46. data/contrib/zstd/lib/decompress/huf_decompress.c +158 -50
  47. data/contrib/zstd/lib/decompress/zstd_decompress.c +884 -699
  48. data/contrib/zstd/lib/deprecated/zbuff.h +5 -4
  49. data/contrib/zstd/lib/deprecated/zbuff_common.c +5 -5
  50. data/contrib/zstd/lib/deprecated/zbuff_compress.c +6 -4
  51. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +5 -4
  52. data/contrib/zstd/lib/dictBuilder/cover.c +93 -77
  53. data/contrib/zstd/lib/dictBuilder/zdict.c +107 -92
  54. data/contrib/zstd/lib/dictBuilder/zdict.h +112 -102
  55. data/contrib/zstd/lib/legacy/zstd_legacy.h +9 -4
  56. data/contrib/zstd/lib/legacy/zstd_v01.c +7 -6
  57. data/contrib/zstd/lib/legacy/zstd_v01.h +5 -4
  58. data/contrib/zstd/lib/legacy/zstd_v02.c +27 -99
  59. data/contrib/zstd/lib/legacy/zstd_v02.h +5 -4
  60. data/contrib/zstd/lib/legacy/zstd_v03.c +26 -98
  61. data/contrib/zstd/lib/legacy/zstd_v03.h +5 -4
  62. data/contrib/zstd/lib/legacy/zstd_v04.c +22 -91
  63. data/contrib/zstd/lib/legacy/zstd_v04.h +5 -4
  64. data/contrib/zstd/lib/legacy/zstd_v05.c +23 -99
  65. data/contrib/zstd/lib/legacy/zstd_v05.h +5 -4
  66. data/contrib/zstd/lib/legacy/zstd_v06.c +22 -96
  67. data/contrib/zstd/lib/legacy/zstd_v06.h +5 -4
  68. data/contrib/zstd/lib/legacy/zstd_v07.c +19 -95
  69. data/contrib/zstd/lib/legacy/zstd_v07.h +5 -4
  70. data/contrib/zstd/lib/zstd.h +895 -271
  71. data/ext/extconf.rb +11 -2
  72. data/ext/extzstd.c +45 -128
  73. data/ext/extzstd.h +74 -31
  74. data/ext/extzstd_stream.c +401 -142
  75. data/ext/zstd_common.c +5 -0
  76. data/ext/zstd_compress.c +8 -0
  77. data/ext/zstd_decompress.c +1 -0
  78. data/ext/zstd_dictbuilder.c +2 -0
  79. data/lib/extzstd/version.rb +1 -1
  80. data/lib/extzstd.rb +48 -1
  81. data/test/test_basic.rb +9 -1
  82. metadata +17 -7
  83. data/HISTORY.ja +0 -10
  84. data/contrib/zstd/LICENSE-examples +0 -11
  85. data/contrib/zstd/PATENTS +0 -33
@@ -1,23 +1,32 @@
1
1
  Zstandard library files
2
2
  ================================
3
3
 
4
- The __lib__ directory contains several directories.
5
- Depending on target use case, it's enough to include only files from relevant directories.
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
- Some additional API may be useful if you're looking into advanced features :
17
- - common/error_public.h : transforms `size_t` function results into an `enum`,
18
- for precise error handling.
19
- - ZSTD_STATIC_LINKING_ONLY : if you define this macro _before_ including `zstd.h`,
20
- it will give access to advanced and experimental API.
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/` is required in all circumstances.
29
- You can select to support compression only, by just adding files from the `compress/` directory,
30
- In a similar way, you can build a decompressor-only library with the `decompress/` directory.
31
-
32
- Other optional functionalities provided are :
33
-
34
- - `dictBuilder/` : source files to create dictionaries.
35
- The API can be consulted in `dictBuilder/zdict.h`.
36
- This module also depends on `common/` and `compress/` .
37
-
38
- - `legacy/` : source code to decompress previous versions of zstd, starting from `v0.1`.
39
- This module also depends on `common/` and `decompress/` .
40
- Library compilation must include directive `ZSTD_LEGACY_SUPPORT = 1` .
41
- The main API can be consulted in `legacy/zstd_legacy.h`.
42
- Advanced API from each version can be found in their relevant header file.
43
- For example, advanced API for version `v0.4` is in `legacy/zstd_v04.h` .
44
-
45
-
46
- #### Using MinGW+MSYS to create DLL
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
- #### Obsolete streaming API
91
+ #### Deprecated API
63
92
 
64
- Streaming is now provided within `zstd.h`.
65
- Older streaming API is still available within `deprecated/zbuff.h`.
66
- It will be removed in a future version.
67
- Consider migrating code towards newer streaming API in `zstd.h`.
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 compile or install zstd library (static and dynamic)
76
- - libzstd.pc.in : for pkg-config (`make install`)
77
- - README.md : this file
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-2016, Yann Collet.
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
- * A critical property of these streams is that they encode and decode in **reverse** direction.
72
- * So the first bit sequence you add will be the last to be read, like a LIFO stack.
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
- int bitPos;
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 (register U32 val)
170
+ MEM_STATIC unsigned BIT_highbit32 (U32 val)
158
171
  {
172
+ assert(val != 0);
173
+ {
159
174
  # if defined(_MSC_VER) /* Visual */
160
- unsigned long r=0;
161
- _BitScanReverse ( &r, val );
162
- return (unsigned) r;
175
+ unsigned long r=0;
176
+ _BitScanReverse ( &r, val );
177
+ return (unsigned) r;
163
178
  # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
164
- return 31 - __builtin_clz (val);
179
+ return 31 - __builtin_clz (val);
165
180
  # else /* Software version */
166
- static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
167
- U32 v = val;
168
- v |= v >> 1;
169
- v |= v >> 2;
170
- v |= v >> 4;
171
- v |= v >> 8;
172
- v |= v >> 16;
173
- return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
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[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF }; /* up to 26 bits */
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(void*)
210
+ * `dstCapacity` must be > sizeof(size_t)
186
211
  * @return : 0 if success,
187
- otherwise an error code (can be tested using ERR_isError() ) */
188
- MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
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->ptr);
195
- if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
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
- can add up to 26 bits into `bitC`.
201
- Does not check for register overflow ! */
202
- MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
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, size_t value, unsigned nbBits)
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; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
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. This will be revealed later on using BIT_closeCStream() */
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; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
276
+ bitC->bitContainer >>= nbBytes*8;
238
277
  }
239
278
 
240
279
  /*! BIT_closeCStream() :
241
280
  * @return : size of CStream, in bytes,
242
- or 0 if it could not fit into dstBuffer */
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
- * bitStream decoding
292
+ * bitStream decoding
256
293
  **********************************************************/
257
294
  /*! BIT_initDStream() :
258
- * Initialize a BIT_DStream_t.
259
- * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
260
- * `srcSize` must be the *exact* size of the bitStream, in bytes.
261
- * @return : size of stream (== srcSize) or an errorCode if a problem is detected
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
- case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
281
- case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
282
- case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
283
- case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
284
- case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
285
- case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
286
- default:;
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
- * @return : value extracted
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 bitMask = sizeof(bitD->bitContainer)*8 - 1;
334
- return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
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
- * unsafe version; only works only if nbBits >= 1 */
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 bitMask = sizeof(bitD->bitContainer)*8 - 1;
343
- return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
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
- * @return : extracted value.
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
- * unsafe version; only works only if nbBits >= 1 */
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
- * Refill `bitD` from buffer previously set in BIT_initDStream() .
374
- * This function is safe, it guarantees it will not read beyond src buffer.
375
- * @return : status of `BIT_DStream_t` internal register.
376
- if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
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
- if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */
380
- return BIT_DStream_overflow;
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->start + sizeof(bitD->bitContainer)) {
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
- * @return Tells if DStream has exactly reached its end (all bits consumed).
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 */