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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +81 -11
- data/ext/zstdruby/common.h +172 -1
- data/ext/zstdruby/extconf.rb +3 -1
- data/ext/zstdruby/libzstd/common/allocations.h +1 -1
- data/ext/zstdruby/libzstd/common/bitstream.h +49 -29
- data/ext/zstdruby/libzstd/common/compiler.h +114 -22
- data/ext/zstdruby/libzstd/common/cpu.h +36 -0
- data/ext/zstdruby/libzstd/common/debug.c +6 -0
- data/ext/zstdruby/libzstd/common/debug.h +20 -11
- data/ext/zstdruby/libzstd/common/error_private.h +45 -36
- data/ext/zstdruby/libzstd/common/fse.h +3 -2
- data/ext/zstdruby/libzstd/common/fse_decompress.c +19 -17
- data/ext/zstdruby/libzstd/common/huf.h +14 -1
- data/ext/zstdruby/libzstd/common/mem.h +0 -9
- data/ext/zstdruby/libzstd/common/pool.c +1 -1
- data/ext/zstdruby/libzstd/common/pool.h +1 -1
- data/ext/zstdruby/libzstd/common/portability_macros.h +2 -0
- data/ext/zstdruby/libzstd/common/threading.c +8 -2
- data/ext/zstdruby/libzstd/common/xxhash.c +5 -11
- data/ext/zstdruby/libzstd/common/xxhash.h +2341 -1007
- data/ext/zstdruby/libzstd/common/zstd_internal.h +5 -5
- data/ext/zstdruby/libzstd/compress/fse_compress.c +8 -7
- data/ext/zstdruby/libzstd/compress/huf_compress.c +54 -25
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +282 -161
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +29 -27
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +224 -113
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +19 -13
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +17 -5
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +11 -0
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +14 -6
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +129 -87
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +103 -28
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +8 -2
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +216 -112
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +31 -7
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +94 -79
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +188 -126
- data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +38 -19
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +84 -32
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +231 -208
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +1 -1
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +2 -0
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +16 -12
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +2 -8
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +2 -2
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +12 -6
- data/ext/zstdruby/libzstd/zstd.h +129 -60
- data/ext/zstdruby/main.c +2 -1
- data/ext/zstdruby/skippable_frame.c +1 -1
- data/ext/zstdruby/streaming_compress.c +75 -23
- data/ext/zstdruby/streaming_decompress.c +41 -40
- data/ext/zstdruby/zstdruby.c +60 -52
- data/lib/zstd-ruby/stream_reader.rb +22 -0
- data/lib/zstd-ruby/stream_writer.rb +23 -0
- data/lib/zstd-ruby/version.rb +1 -1
- data/lib/zstd-ruby.rb +2 -0
- data/renovate.json +6 -0
- data/zstd-ruby.gemspec +2 -1
- metadata +20 -4
- data/ext/zstdruby/streaming_compress.h +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fe1a5bcfa102673b36ea9a48096636faa76535095211998cddfe316775a3d78
|
4
|
+
data.tar.gz: e2a96d0d1d2bdda0bc3d34080df219aeaa8c5274a2dac7a838730fce54ebe4f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bdffd7e5b2d824fdf5ebad116ef4b965c4d4d2a77898df5a51623020db6fddf0e4562aa4d80de7f8978fa5f557ce85e56d19042667c379b3ac97c3a274a9d11
|
7
|
+
data.tar.gz: 639a3d64cf8a8fa36a10cf180560a4102516d4da21e3100c1cdd724732fb583449c828ac4eeef6f9bad89c2f22467f7adf80b083116121ccff8d356c58246966
|
data/.gitignore
CHANGED
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.
|
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
|
-
###
|
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
|
43
|
+
compressed_data = Zstd.compress(data, level: complession_level) # default compression_level is 3
|
42
44
|
```
|
43
45
|
|
44
|
-
|
46
|
+
#### Compression with Dictionary
|
45
47
|
```ruby
|
46
48
|
# dictionary is supposed to have been created using `zstd --train`
|
47
|
-
compressed_using_dict = Zstd.
|
49
|
+
compressed_using_dict = Zstd.compress("", dict: File.read('dictionary_file'))
|
48
50
|
```
|
49
51
|
|
50
|
-
|
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
|
-
|
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
|
-
|
97
|
+
#### Decompression with Dictionary
|
76
98
|
```ruby
|
77
99
|
# dictionary is supposed to have been created using `zstd --train`
|
78
|
-
Zstd.
|
100
|
+
Zstd.decompress(compressed_using_dict, dict: File.read('dictionary_file'))
|
79
101
|
```
|
80
102
|
|
81
|
-
|
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
|
-
|
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
|
|
data/ext/zstdruby/common.h
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
#ifndef ZSTD_RUBY_H
|
2
2
|
#define ZSTD_RUBY_H 1
|
3
3
|
|
4
|
-
#include
|
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, ¶ms, 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, ¶ms, 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, ¶ms, 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, ¶ms, 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 */
|
data/ext/zstdruby/extconf.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "mkmf"
|
2
2
|
|
3
|
-
|
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 "
|
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
|
-
|
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
|
105
|
-
|
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 (
|
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
|
-
|
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 += (
|
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 += (
|
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 += (
|
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 += (
|
280
|
+
case 4: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[3]) << 24;
|
280
281
|
ZSTD_FALLTHROUGH;
|
281
282
|
|
282
|
-
case 3: bitD->bitContainer += (
|
283
|
+
case 3: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[2]) << 16;
|
283
284
|
ZSTD_FALLTHROUGH;
|
284
285
|
|
285
|
-
case 2: bitD->bitContainer += (
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
411
|
+
FORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
400
412
|
{
|
401
|
-
|
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
|
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) {
|