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.
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 */