zstd-ruby 1.5.5.0 → 1.5.6.6

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +81 -11
  4. data/ext/zstdruby/common.h +172 -1
  5. data/ext/zstdruby/extconf.rb +3 -1
  6. data/ext/zstdruby/libzstd/common/allocations.h +1 -1
  7. data/ext/zstdruby/libzstd/common/bitstream.h +49 -29
  8. data/ext/zstdruby/libzstd/common/compiler.h +114 -22
  9. data/ext/zstdruby/libzstd/common/cpu.h +36 -0
  10. data/ext/zstdruby/libzstd/common/debug.c +6 -0
  11. data/ext/zstdruby/libzstd/common/debug.h +20 -11
  12. data/ext/zstdruby/libzstd/common/error_private.h +45 -36
  13. data/ext/zstdruby/libzstd/common/fse.h +3 -2
  14. data/ext/zstdruby/libzstd/common/fse_decompress.c +19 -17
  15. data/ext/zstdruby/libzstd/common/huf.h +14 -1
  16. data/ext/zstdruby/libzstd/common/mem.h +0 -9
  17. data/ext/zstdruby/libzstd/common/pool.c +1 -1
  18. data/ext/zstdruby/libzstd/common/pool.h +1 -1
  19. data/ext/zstdruby/libzstd/common/portability_macros.h +2 -0
  20. data/ext/zstdruby/libzstd/common/threading.c +8 -2
  21. data/ext/zstdruby/libzstd/common/xxhash.c +5 -11
  22. data/ext/zstdruby/libzstd/common/xxhash.h +2341 -1007
  23. data/ext/zstdruby/libzstd/common/zstd_internal.h +5 -5
  24. data/ext/zstdruby/libzstd/compress/fse_compress.c +8 -7
  25. data/ext/zstdruby/libzstd/compress/huf_compress.c +54 -25
  26. data/ext/zstdruby/libzstd/compress/zstd_compress.c +282 -161
  27. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +29 -27
  28. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +224 -113
  29. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +19 -13
  30. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +17 -5
  31. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +11 -0
  32. data/ext/zstdruby/libzstd/compress/zstd_fast.c +14 -6
  33. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +129 -87
  34. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +103 -28
  35. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +8 -2
  36. data/ext/zstdruby/libzstd/compress/zstd_opt.c +216 -112
  37. data/ext/zstdruby/libzstd/compress/zstd_opt.h +31 -7
  38. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +94 -79
  39. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +188 -126
  40. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +38 -19
  41. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +84 -32
  42. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +231 -208
  43. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +1 -1
  44. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +2 -0
  45. data/ext/zstdruby/libzstd/dictBuilder/cover.c +16 -12
  46. data/ext/zstdruby/libzstd/dictBuilder/cover.h +2 -8
  47. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +2 -2
  48. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +12 -6
  49. data/ext/zstdruby/libzstd/zstd.h +129 -60
  50. data/ext/zstdruby/main.c +2 -1
  51. data/ext/zstdruby/skippable_frame.c +1 -1
  52. data/ext/zstdruby/streaming_compress.c +75 -23
  53. data/ext/zstdruby/streaming_decompress.c +41 -40
  54. data/ext/zstdruby/zstdruby.c +60 -52
  55. data/lib/zstd-ruby/stream_reader.rb +22 -0
  56. data/lib/zstd-ruby/stream_writer.rb +23 -0
  57. data/lib/zstd-ruby/version.rb +1 -1
  58. data/lib/zstd-ruby.rb +2 -0
  59. data/renovate.json +6 -0
  60. data/zstd-ruby.gemspec +2 -1
  61. metadata +20 -4
  62. data/ext/zstdruby/streaming_compress.h +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76dbffc6a0a13fccd92ea93abd90e33c4a26ab2ac2972877b7928a515e37033e
4
- data.tar.gz: 21e3eba574ac94d9f34ac0d33732435ed3fd2373e9db921702a74d2a2c9d606a
3
+ metadata.gz: 1fe1a5bcfa102673b36ea9a48096636faa76535095211998cddfe316775a3d78
4
+ data.tar.gz: e2a96d0d1d2bdda0bc3d34080df219aeaa8c5274a2dac7a838730fce54ebe4f6
5
5
  SHA512:
6
- metadata.gz: 4f8c40ad6eaa9b014467fc57651f857713767f7930b2e7e2060c50ff58d05262416d0e9cb1427f440298af577eeef5247daec1866a55003ca6d9b2e2ea6212de
7
- data.tar.gz: 5836f8061f7588081df400bf0705fcc74003029ec9ef9225e43f5ba5a0b19ec747af71cf0e34f150212a5efd90b9e1ea5ebe49a7231297e3f2ab8080bbf8247d
6
+ metadata.gz: 6bdffd7e5b2d824fdf5ebad116ef4b965c4d4d2a77898df5a51623020db6fddf0e4562aa4d80de7f8978fa5f557ce85e56d19042667c379b3ac97c3a274a9d11
7
+ data.tar.gz: 639a3d64cf8a8fa36a10cf180560a4102516d4da21e3100c1cdd724732fb583449c828ac4eeef6f9bad89c2f22467f7adf80b083116121ccff8d356c58246966
data/.gitignore CHANGED
@@ -19,3 +19,5 @@ vendor/
19
19
  .rspec_status
20
20
 
21
21
  .ruby-version
22
+
23
+ .vscode
data/README.md CHANGED
@@ -10,7 +10,7 @@ See https://github.com/facebook/zstd
10
10
  Fork from https://github.com/jarredholman/ruby-zstd.
11
11
 
12
12
  ## Zstd version
13
- v1.5.5 (https://github.com/facebook/zstd/tree/v1.5.5)
13
+ [v1.5.6](https://github.com/facebook/zstd/tree/v1.5.6)
14
14
 
15
15
  ## Installation
16
16
 
@@ -34,20 +34,22 @@ Or install it yourself as:
34
34
  require 'zstd-ruby'
35
35
  ```
36
36
 
37
- ### Simple Compression
37
+ ### Compression
38
+
39
+ #### Simple Compression
38
40
 
39
41
  ```ruby
40
42
  compressed_data = Zstd.compress(data)
41
- compressed_data = Zstd.compress(data, complession_level) # default compression_level is 0
43
+ compressed_data = Zstd.compress(data, level: complession_level) # default compression_level is 3
42
44
  ```
43
45
 
44
- ### Compression using Dictionary
46
+ #### Compression with Dictionary
45
47
  ```ruby
46
48
  # dictionary is supposed to have been created using `zstd --train`
47
- compressed_using_dict = Zstd.compress_using_dict("", IO.read('dictionary_file'))
49
+ compressed_using_dict = Zstd.compress("", dict: File.read('dictionary_file'))
48
50
  ```
49
51
 
50
- ### Streaming Compression
52
+ #### Streaming Compression
51
53
  ```ruby
52
54
  stream = Zstd::StreamingCompress.new
53
55
  stream << "abc" << "def"
@@ -66,19 +68,39 @@ res << stream.compress("def")
66
68
  res << stream.finish
67
69
  ```
68
70
 
69
- ### Simple Decompression
71
+ #### Streaming Compression with Dictionary
72
+ ```ruby
73
+ stream = Zstd::StreamingCompress.new(dict: File.read('dictionary_file'))
74
+ stream << "abc" << "def"
75
+ res = stream.flush
76
+ stream << "ghi"
77
+ res << stream.finish
78
+ ```
79
+
80
+ #### Streaming Compression with level and Dictionary
81
+ ```ruby
82
+ stream = Zstd::StreamingCompress.new(level: 5, dict: File.read('dictionary_file'))
83
+ stream << "abc" << "def"
84
+ res = stream.flush
85
+ stream << "ghi"
86
+ res << stream.finish
87
+ ```
88
+
89
+ ### Decompression
90
+
91
+ #### Simple Decompression
70
92
 
71
93
  ```ruby
72
94
  data = Zstd.decompress(compressed_data)
73
95
  ```
74
96
 
75
- ### Decomporession using Dictionary
97
+ #### Decompression with Dictionary
76
98
  ```ruby
77
99
  # dictionary is supposed to have been created using `zstd --train`
78
- Zstd.decompress_using_dict(compressed_using_dict, IO.read('dictionary_file'))
100
+ Zstd.decompress(compressed_using_dict, dict: File.read('dictionary_file'))
79
101
  ```
80
102
 
81
- ### Streaming Decompression
103
+ #### Streaming Decompression
82
104
  ```ruby
83
105
  cstr = "" # Compressed data
84
106
  stream = Zstd::StreamingDecompress.new
@@ -87,7 +109,16 @@ result << stream.decompress(cstr[0, 10])
87
109
  result << stream.decompress(cstr[10..-1])
88
110
  ```
89
111
 
90
- ### Skippable flame
112
+ #### Streaming Decompression with dictionary
113
+ ```ruby
114
+ cstr = "" # Compressed data
115
+ stream = Zstd::StreamingDecompress.new(dict: File.read('dictionary_file'))
116
+ result = ''
117
+ result << stream.decompress(cstr[0, 10])
118
+ result << stream.decompress(cstr[10..-1])
119
+ ```
120
+
121
+ ### Skippable frame
91
122
 
92
123
  ```ruby
93
124
  compressed_data_with_skippable_frame = Zstd.write_skippable_frame(compressed_data, "sample data")
@@ -96,6 +127,45 @@ Zstd.read_skippable_frame(compressed_data_with_skippable_frame)
96
127
  # => "sample data"
97
128
  ```
98
129
 
130
+ ### Stream Writer and Reader Wrapper
131
+ **EXPERIMENTAL**
132
+
133
+ * These features are experimental and may be subject to API changes in future releases.
134
+ * There may be performance and compatibility issues, so extensive testing is required before production use.
135
+ * If you have any questions, encounter bugs, or have suggestions, please report them via [GitHub issues](https://github.com/SpringMT/zstd-ruby/issues).
136
+
137
+ #### Zstd::StreamWriter
138
+
139
+ ```ruby
140
+ require 'stringio'
141
+ require 'zstd-ruby'
142
+
143
+ io = StringIO.new
144
+ stream = Zstd::StreamWriter.new(io)
145
+ stream.write("abc")
146
+ stream.finish
147
+
148
+ io.rewind
149
+ # Retrieve the compressed data
150
+ compressed_data = io.read
151
+ ```
152
+
153
+ #### Zstd::StreamReader
154
+
155
+ ```ruby
156
+ require 'stringio'
157
+ require 'zstd-ruby' # Add the appropriate require statement if necessary
158
+
159
+ io = StringIO.new(compressed_data)
160
+ reader = Zstd::StreamReader.new(io)
161
+
162
+ # Read and output the decompressed data
163
+ puts reader.read(10) # 'abc'
164
+ puts reader.read(10) # 'def'
165
+ puts reader.read(10) # '' (end of data)
166
+ ```
167
+
168
+
99
169
  ## JRuby
100
170
  This gem does not support JRuby.
101
171
 
@@ -1,7 +1,11 @@
1
1
  #ifndef ZSTD_RUBY_H
2
2
  #define ZSTD_RUBY_H 1
3
3
 
4
- #include "ruby.h"
4
+ #include <ruby.h>
5
+ #ifdef HAVE_RUBY_THREAD_H
6
+ #include <ruby/thread.h>
7
+ #endif
8
+ #include <stdbool.h>
5
9
  #include "./libzstd/zstd.h"
6
10
 
7
11
  static int convert_compression_level(VALUE compression_level_value)
@@ -12,4 +16,171 @@ static int convert_compression_level(VALUE compression_level_value)
12
16
  return NUM2INT(compression_level_value);
13
17
  }
14
18
 
19
+ static void set_compress_params(ZSTD_CCtx* const ctx, VALUE level_from_args, VALUE kwargs)
20
+ {
21
+ ID kwargs_keys[2];
22
+ kwargs_keys[0] = rb_intern("level");
23
+ kwargs_keys[1] = rb_intern("dict");
24
+ VALUE kwargs_values[2];
25
+ rb_get_kwargs(kwargs, kwargs_keys, 0, 2, kwargs_values);
26
+
27
+ int compression_level = ZSTD_CLEVEL_DEFAULT;
28
+ if (kwargs_values[0] != Qundef && kwargs_values[0] != Qnil) {
29
+ compression_level = convert_compression_level(kwargs_values[0]);
30
+ } else if (!NIL_P(level_from_args)) {
31
+ rb_warn("`level` in args is deprecated; use keyword args `level:` instead.");
32
+ compression_level = convert_compression_level(level_from_args);
33
+ }
34
+ ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, compression_level);
35
+
36
+ if (kwargs_values[1] != Qundef && kwargs_values[1] != Qnil) {
37
+ char* dict_buffer = RSTRING_PTR(kwargs_values[1]);
38
+ size_t dict_size = RSTRING_LEN(kwargs_values[1]);
39
+ size_t load_dict_ret = ZSTD_CCtx_loadDictionary(ctx, dict_buffer, dict_size);
40
+ if (ZSTD_isError(load_dict_ret)) {
41
+ ZSTD_freeCCtx(ctx);
42
+ rb_raise(rb_eRuntimeError, "%s", "ZSTD_CCtx_loadDictionary failed");
43
+ }
44
+ }
45
+ }
46
+
47
+ struct stream_compress_params {
48
+ ZSTD_CCtx* ctx;
49
+ ZSTD_outBuffer* output;
50
+ ZSTD_inBuffer* input;
51
+ ZSTD_EndDirective endOp;
52
+ size_t ret;
53
+ };
54
+
55
+ static void* stream_compress_wrapper(void* args)
56
+ {
57
+ struct stream_compress_params* params = args;
58
+ params->ret = ZSTD_compressStream2(params->ctx, params->output, params->input, params->endOp);
59
+ return NULL;
60
+ }
61
+
62
+ static size_t zstd_stream_compress(ZSTD_CCtx* const ctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input, ZSTD_EndDirective endOp, bool gvl)
63
+ {
64
+ #ifdef HAVE_RUBY_THREAD_H
65
+ if (gvl) {
66
+ return ZSTD_compressStream2(ctx, output, input, endOp);
67
+ } else {
68
+ struct stream_compress_params params = { ctx, output, input, endOp };
69
+ rb_thread_call_without_gvl(stream_compress_wrapper, &params, NULL, NULL);
70
+ return params.ret;
71
+ }
72
+ #else
73
+ return ZSTD_compressStream2(ctx, output, input, endOp);
74
+ #endif
75
+ }
76
+
77
+ struct compress_params {
78
+ ZSTD_CCtx* ctx;
79
+ char* output_data;
80
+ size_t output_size;
81
+ char* input_data;
82
+ size_t input_size;
83
+ size_t ret;
84
+ };
85
+
86
+ static void* compress_wrapper(void* args)
87
+ {
88
+ struct compress_params* params = args;
89
+ params->ret = ZSTD_compress2(params->ctx ,params->output_data, params->output_size, params->input_data, params->input_size);
90
+ return NULL;
91
+ }
92
+
93
+ static size_t zstd_compress(ZSTD_CCtx* const ctx, char* output_data, size_t output_size, char* input_data, size_t input_size, bool gvl)
94
+ {
95
+ #ifdef HAVE_RUBY_THREAD_H
96
+ if (gvl) {
97
+ return ZSTD_compress2(ctx , output_data, output_size, input_data, input_size);
98
+ } else {
99
+ struct compress_params params = { ctx, output_data, output_size, input_data, input_size };
100
+ rb_thread_call_without_gvl(compress_wrapper, &params, NULL, NULL);
101
+ return params.ret;
102
+ }
103
+ #else
104
+ return ZSTD_compress2(ctx , output_data, output_size, input_data, input_size);
105
+ #endif
106
+ }
107
+
108
+ static void set_decompress_params(ZSTD_DCtx* const dctx, VALUE kwargs)
109
+ {
110
+ ID kwargs_keys[1];
111
+ kwargs_keys[0] = rb_intern("dict");
112
+ VALUE kwargs_values[1];
113
+ rb_get_kwargs(kwargs, kwargs_keys, 0, 1, kwargs_values);
114
+
115
+ if (kwargs_values[0] != Qundef && kwargs_values[0] != Qnil) {
116
+ char* dict_buffer = RSTRING_PTR(kwargs_values[0]);
117
+ size_t dict_size = RSTRING_LEN(kwargs_values[0]);
118
+ size_t load_dict_ret = ZSTD_DCtx_loadDictionary(dctx, dict_buffer, dict_size);
119
+ if (ZSTD_isError(load_dict_ret)) {
120
+ ZSTD_freeDCtx(dctx);
121
+ rb_raise(rb_eRuntimeError, "%s", "ZSTD_CCtx_loadDictionary failed");
122
+ }
123
+ }
124
+ }
125
+
126
+ struct stream_decompress_params {
127
+ ZSTD_DCtx* dctx;
128
+ ZSTD_outBuffer* output;
129
+ ZSTD_inBuffer* input;
130
+ size_t ret;
131
+ };
132
+
133
+ static void* stream_decompress_wrapper(void* args)
134
+ {
135
+ struct stream_decompress_params* params = args;
136
+ params->ret = ZSTD_decompressStream(params->dctx, params->output, params->input);
137
+ return NULL;
138
+ }
139
+
140
+ static size_t zstd_stream_decompress(ZSTD_DCtx* const dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input, bool gvl)
141
+ {
142
+ #ifdef HAVE_RUBY_THREAD_H
143
+ if (gvl) {
144
+ return ZSTD_decompressStream(dctx, output, input);
145
+ } else {
146
+ struct stream_decompress_params params = { dctx, output, input };
147
+ rb_thread_call_without_gvl(stream_decompress_wrapper, &params, NULL, NULL);
148
+ return params.ret;
149
+ }
150
+ #else
151
+ return ZSTD_decompressStream(dctx, output, input);
152
+ #endif
153
+ }
154
+
155
+ struct decompress_params {
156
+ ZSTD_DCtx* dctx;
157
+ char* output_data;
158
+ size_t output_size;
159
+ char* input_data;
160
+ size_t input_size;
161
+ size_t ret;
162
+ };
163
+
164
+ static void* decompress_wrapper(void* args)
165
+ {
166
+ struct decompress_params* params = args;
167
+ params->ret = ZSTD_decompressDCtx(params->dctx, params->output_data, params->output_size, params->input_data, params->input_size);
168
+ return NULL;
169
+ }
170
+
171
+ static size_t zstd_decompress(ZSTD_DCtx* const dctx, char* output_data, size_t output_size, char* input_data, size_t input_size, bool gvl)
172
+ {
173
+ #ifdef HAVE_RUBY_THREAD_H
174
+ if (gvl) {
175
+ return ZSTD_decompressDCtx(dctx, output_data, output_size, input_data, input_size);
176
+ } else {
177
+ struct decompress_params params = { dctx, output_data, output_size, input_data, input_size };
178
+ rb_thread_call_without_gvl(decompress_wrapper, &params, NULL, NULL);
179
+ return params.ret;
180
+ }
181
+ #else
182
+ return ZSTD_decompressDCtx(dctx, output_data, output_size, input_data, input_size);
183
+ #endif
184
+ }
185
+
15
186
  #endif /* ZSTD_RUBY_H */
@@ -1,6 +1,8 @@
1
1
  require "mkmf"
2
2
 
3
- $CFLAGS = '-I. -O3 -std=c99 -DZSTD_STATIC_LINKING_ONLY'
3
+ have_func('rb_gc_mark_movable')
4
+
5
+ $CFLAGS = '-I. -O3 -std=c99 -DZSTD_STATIC_LINKING_ONLY -DZSTD_MULTITHREAD -pthread -DDEBUGLEVEL=0'
4
6
  $CPPFLAGS += " -fdeclspec" if CONFIG['CXX'] =~ /clang/
5
7
 
6
8
  Dir.chdir File.expand_path('..', __FILE__) do
@@ -14,7 +14,7 @@
14
14
  #define ZSTD_DEPS_NEED_MALLOC
15
15
  #include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */
16
16
 
17
- #include "mem.h" /* MEM_STATIC */
17
+ #include "compiler.h" /* MEM_STATIC */
18
18
  #define ZSTD_STATIC_LINKING_ONLY
19
19
  #include "../zstd.h" /* ZSTD_customMem */
20
20
 
@@ -90,19 +90,20 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
90
90
  /*-********************************************
91
91
  * bitStream decoding API (read backward)
92
92
  **********************************************/
93
+ typedef size_t BitContainerType;
93
94
  typedef struct {
94
- size_t bitContainer;
95
+ BitContainerType bitContainer;
95
96
  unsigned bitsConsumed;
96
97
  const char* ptr;
97
98
  const char* start;
98
99
  const char* limitPtr;
99
100
  } BIT_DStream_t;
100
101
 
101
- typedef enum { BIT_DStream_unfinished = 0,
102
- BIT_DStream_endOfBuffer = 1,
103
- BIT_DStream_completed = 2,
104
- BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
105
- /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
102
+ typedef enum { BIT_DStream_unfinished = 0, /* fully refilled */
103
+ BIT_DStream_endOfBuffer = 1, /* still some bits left in bitstream */
104
+ BIT_DStream_completed = 2, /* bitstream entirely consumed, bit-exact */
105
+ BIT_DStream_overflow = 3 /* user requested more bits than present in bitstream */
106
+ } BIT_DStream_status; /* result of BIT_reloadDStream() */
106
107
 
107
108
  MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
108
109
  MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
@@ -112,7 +113,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
112
113
 
113
114
  /* Start by invoking BIT_initDStream().
114
115
  * A chunk of the bitStream is then stored into a local register.
115
- * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
116
+ * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (BitContainerType).
116
117
  * You can then retrieve bitFields stored into the local register, **in reverse order**.
117
118
  * Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
118
119
  * A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
@@ -162,7 +163,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
162
163
  return 0;
163
164
  }
164
165
 
165
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
166
+ FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
166
167
  {
167
168
  #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS)
168
169
  return _bzhi_u64(bitContainer, nbBits);
@@ -267,22 +268,22 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
267
268
  bitD->bitContainer = *(const BYTE*)(bitD->start);
268
269
  switch(srcSize)
269
270
  {
270
- case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
271
+ case 7: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
271
272
  ZSTD_FALLTHROUGH;
272
273
 
273
- case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
274
+ case 6: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
274
275
  ZSTD_FALLTHROUGH;
275
276
 
276
- case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
277
+ case 5: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
277
278
  ZSTD_FALLTHROUGH;
278
279
 
279
- case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
280
+ case 4: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[3]) << 24;
280
281
  ZSTD_FALLTHROUGH;
281
282
 
282
- case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
283
+ case 3: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[2]) << 16;
283
284
  ZSTD_FALLTHROUGH;
284
285
 
285
- case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
286
+ case 2: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[1]) << 8;
286
287
  ZSTD_FALLTHROUGH;
287
288
 
288
289
  default: break;
@@ -297,12 +298,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
297
298
  return srcSize;
298
299
  }
299
300
 
300
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
301
+ FORCE_INLINE_TEMPLATE size_t BIT_getUpperBits(BitContainerType bitContainer, U32 const start)
301
302
  {
302
303
  return bitContainer >> start;
303
304
  }
304
305
 
305
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
306
+ FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits)
306
307
  {
307
308
  U32 const regMask = sizeof(bitContainer)*8 - 1;
308
309
  /* if start > regMask, bitstream is corrupted, and result is undefined */
@@ -325,7 +326,7 @@ MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 c
325
326
  * On 32-bits, maxNbBits==24.
326
327
  * On 64-bits, maxNbBits==56.
327
328
  * @return : value extracted */
328
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
329
+ FORCE_INLINE_TEMPLATE size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
329
330
  {
330
331
  /* arbitrate between double-shift and shift+mask */
331
332
  #if 1
@@ -348,7 +349,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
348
349
  return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
349
350
  }
350
351
 
351
- MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
352
+ FORCE_INLINE_TEMPLATE void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
352
353
  {
353
354
  bitD->bitsConsumed += nbBits;
354
355
  }
@@ -357,7 +358,7 @@ MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
357
358
  * Read (consume) next n bits from local register and update.
358
359
  * Pay attention to not read more than nbBits contained into local register.
359
360
  * @return : extracted value. */
360
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
361
+ FORCE_INLINE_TEMPLATE size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
361
362
  {
362
363
  size_t const value = BIT_lookBits(bitD, nbBits);
363
364
  BIT_skipBits(bitD, nbBits);
@@ -374,6 +375,21 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
374
375
  return value;
375
376
  }
376
377
 
378
+ /*! BIT_reloadDStream_internal() :
379
+ * Simple variant of BIT_reloadDStream(), with two conditions:
380
+ * 1. bitstream is valid : bitsConsumed <= sizeof(bitD->bitContainer)*8
381
+ * 2. look window is valid after shifted down : bitD->ptr >= bitD->start
382
+ */
383
+ MEM_STATIC BIT_DStream_status BIT_reloadDStream_internal(BIT_DStream_t* bitD)
384
+ {
385
+ assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
386
+ bitD->ptr -= bitD->bitsConsumed >> 3;
387
+ assert(bitD->ptr >= bitD->start);
388
+ bitD->bitsConsumed &= 7;
389
+ bitD->bitContainer = MEM_readLEST(bitD->ptr);
390
+ return BIT_DStream_unfinished;
391
+ }
392
+
377
393
  /*! BIT_reloadDStreamFast() :
378
394
  * Similar to BIT_reloadDStream(), but with two differences:
379
395
  * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
@@ -384,31 +400,35 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
384
400
  {
385
401
  if (UNLIKELY(bitD->ptr < bitD->limitPtr))
386
402
  return BIT_DStream_overflow;
387
- assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
388
- bitD->ptr -= bitD->bitsConsumed >> 3;
389
- bitD->bitsConsumed &= 7;
390
- bitD->bitContainer = MEM_readLEST(bitD->ptr);
391
- return BIT_DStream_unfinished;
403
+ return BIT_reloadDStream_internal(bitD);
392
404
  }
393
405
 
394
406
  /*! BIT_reloadDStream() :
395
407
  * Refill `bitD` from buffer previously set in BIT_initDStream() .
396
- * This function is safe, it guarantees it will not read beyond src buffer.
408
+ * This function is safe, it guarantees it will not never beyond src buffer.
397
409
  * @return : status of `BIT_DStream_t` internal register.
398
410
  * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
399
- MEM_STATIC FORCE_INLINE_ATTR BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
411
+ FORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
400
412
  {
401
- if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
413
+ /* note : once in overflow mode, a bitstream remains in this mode until it's reset */
414
+ if (UNLIKELY(bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))) {
415
+ static const BitContainerType zeroFilled = 0;
416
+ bitD->ptr = (const char*)&zeroFilled; /* aliasing is allowed for char */
417
+ /* overflow detected, erroneous scenario or end of stream: no update */
402
418
  return BIT_DStream_overflow;
419
+ }
420
+
421
+ assert(bitD->ptr >= bitD->start);
403
422
 
404
423
  if (bitD->ptr >= bitD->limitPtr) {
405
- return BIT_reloadDStreamFast(bitD);
424
+ return BIT_reloadDStream_internal(bitD);
406
425
  }
407
426
  if (bitD->ptr == bitD->start) {
427
+ /* reached end of bitStream => no update */
408
428
  if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
409
429
  return BIT_DStream_completed;
410
430
  }
411
- /* start < ptr < limitPtr */
431
+ /* start < ptr < limitPtr => cautious update */
412
432
  { U32 nbBytes = bitD->bitsConsumed >> 3;
413
433
  BIT_DStream_status result = BIT_DStream_unfinished;
414
434
  if (bitD->ptr - nbBytes < bitD->start) {