ruby-zstds 1.0.6 → 1.1.0
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/README.md +32 -19
- data/ext/extconf.rb +5 -0
- data/ext/zstds_ext/buffer.c +4 -3
- data/ext/zstds_ext/buffer.h +5 -5
- data/ext/zstds_ext/dictionary.c +104 -42
- data/ext/zstds_ext/dictionary.h +1 -1
- data/ext/zstds_ext/error.c +1 -1
- data/ext/zstds_ext/error.h +2 -1
- data/ext/zstds_ext/gvl.h +24 -0
- data/ext/zstds_ext/io.c +229 -137
- data/ext/zstds_ext/option.c +44 -43
- data/ext/zstds_ext/option.h +62 -51
- data/ext/zstds_ext/stream/compressor.c +103 -50
- data/ext/zstds_ext/stream/compressor.h +4 -1
- data/ext/zstds_ext/stream/decompressor.c +46 -22
- data/ext/zstds_ext/stream/decompressor.h +4 -1
- data/ext/zstds_ext/string.c +93 -62
- data/lib/zstds/dictionary.rb +2 -0
- data/lib/zstds/option.rb +6 -0
- data/lib/zstds/version.rb +1 -1
- metadata +23 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f860451f1cf45988053d7d5512e26e18a5c5b446f9f75fbf06f3a9ef3103c806
|
4
|
+
data.tar.gz: a224e7b3e16b3f2e1d2785fc024241813e3fb934351e5a851744eb1e2ae82783
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76ee0c342ebb71bf4ae6ac0a6139d3a8d7966da4843eece7c819b84e531fab6e501fa7ebafaa1c864f1200771b2b119ef885a827ba50da27b6112803a2858c7a
|
7
|
+
data.tar.gz: 575a15688165bccf52dc6f73a26fa1ac0f3a1ba0bf010384e9e34ecda8183bb904efb369635f75052420f86c84f59b906d7e46a65f301ab19e2c888d9ca96983
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Ruby bindings for zstd library
|
2
2
|
|
3
|
-
| Travis | AppVeyor | Circle | Codecov |
|
4
|
-
| :---: | :---: | :---: | :---: |
|
5
|
-
| [](https://travis-ci.com/andrew-aladev/ruby-zstds) | [](https://ci.appveyor.com/project/andrew-aladev/ruby-zstds/branch/master) | [](https://circleci.com/gh/andrew-aladev/ruby-zstds/tree/master) | [](https://codecov.io/gh/andrew-aladev/ruby-zstds) |
|
3
|
+
| Travis | AppVeyor | Circle | Codecov | Gem |
|
4
|
+
| :---: | :---: | :---: | :---: | :---: |
|
5
|
+
| [](https://travis-ci.com/andrew-aladev/ruby-zstds) | [](https://ci.appveyor.com/project/andrew-aladev/ruby-zstds/branch/master) | [](https://circleci.com/gh/andrew-aladev/ruby-zstds/tree/master) | [](https://codecov.io/gh/andrew-aladev/ruby-zstds) | [](https://rubygems.org/gems/ruby-zstds) |
|
6
6
|
|
7
7
|
See [zstd library](https://github.com/facebook/zstd).
|
8
8
|
|
@@ -79,7 +79,7 @@ data = ZSTDS::String.compress "sample string", :dictionary => dictionary
|
|
79
79
|
puts ZSTDS::String.decompress(data, :dictionary => dictionary)
|
80
80
|
```
|
81
81
|
|
82
|
-
You can create and read `tar.zst` archives with
|
82
|
+
You can create and read `tar.zst` archives with [minitar](https://github.com/halostatue/minitar) for example.
|
83
83
|
|
84
84
|
```ruby
|
85
85
|
require "zstds"
|
@@ -101,12 +101,25 @@ ZSTDS::Stream::Reader.open "file.tar.zst" do |reader|
|
|
101
101
|
end
|
102
102
|
```
|
103
103
|
|
104
|
+
You can also use `Content-Encoding: zstd` with [sinatra](http://sinatrarb.com):
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
require "zstds"
|
108
|
+
require "sinatra"
|
109
|
+
|
110
|
+
get "/" do
|
111
|
+
headers["Content-Encoding"] = "zstd"
|
112
|
+
ZSTDS::String.compress "sample string"
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
104
116
|
## Options
|
105
117
|
|
106
118
|
| Option | Values | Default | Description |
|
107
119
|
|---------------------------------|----------------|------------|-------------|
|
108
120
|
| `source_buffer_length` | 0 - inf | 0 (auto) | internal buffer length for source data |
|
109
121
|
| `destination_buffer_length` | 0 - inf | 0 (auto) | internal buffer length for description data |
|
122
|
+
| `gvl` | true/false | false | enables global VM lock where possible |
|
110
123
|
| `compression_level` | -131072 - 22 | 0 (auto) | compression level |
|
111
124
|
| `window_log` | 10 - 31 | 0 (auto) | maximum back-reference distance (power of 2) |
|
112
125
|
| `hash_log` | 6 - 30 | 0 (auto) | size of the initial probe table (power of 2) |
|
@@ -134,6 +147,10 @@ There are internal buffers for compressed and decompressed data.
|
|
134
147
|
For example you want to use 1 KB as `source_buffer_length` for compressor - please use 256 B as `destination_buffer_length`.
|
135
148
|
You want to use 256 B as `source_buffer_length` for decompressor - please use 1 KB as `destination_buffer_length`.
|
136
149
|
|
150
|
+
`gvl` is disabled by default, this mode allows running multiple compressors/decompressors in different threads simultaneously.
|
151
|
+
Please consider enabling `gvl` if you don't want to launch processors in separate threads.
|
152
|
+
If `gvl` is enabled ruby won't waste time on acquiring/releasing VM lock.
|
153
|
+
|
137
154
|
`String` and `File` will set `:pledged_size` automaticaly.
|
138
155
|
|
139
156
|
You can also read zstd docs for more info about options.
|
@@ -161,6 +178,7 @@ Possible compressor options:
|
|
161
178
|
```
|
162
179
|
:source_buffer_length
|
163
180
|
:destination_buffer_length
|
181
|
+
:gvl
|
164
182
|
:compression_level
|
165
183
|
:window_log
|
166
184
|
:hash_log
|
@@ -188,6 +206,7 @@ Possible decompressor options:
|
|
188
206
|
```
|
189
207
|
:source_buffer_length
|
190
208
|
:destination_buffer_length
|
209
|
+
:gvl
|
191
210
|
:window_log_max
|
192
211
|
:dictionary
|
193
212
|
```
|
@@ -201,18 +220,6 @@ data = ZSTDS::String.compress "sample string", :compression_level => 5
|
|
201
220
|
puts ZSTDS::String.decompress(data, :window_log_max => 11)
|
202
221
|
```
|
203
222
|
|
204
|
-
HTTP encoding (`Content-Encoding: zstd`) using default options:
|
205
|
-
|
206
|
-
```ruby
|
207
|
-
require "zstds"
|
208
|
-
require "sinatra"
|
209
|
-
|
210
|
-
get "/" do
|
211
|
-
headers["Content-Encoding"] = "zstd"
|
212
|
-
ZSTDS::String.compress "sample string"
|
213
|
-
end
|
214
|
-
```
|
215
|
-
|
216
223
|
## String
|
217
224
|
|
218
225
|
String maintains destination buffer only, so it accepts `destination_buffer_length` option only.
|
@@ -418,12 +425,18 @@ Please use regular constructor to create dictionary from buffer.
|
|
418
425
|
|
419
426
|
Read dictionary id from buffer.
|
420
427
|
|
428
|
+
## Thread safety
|
429
|
+
|
430
|
+
`:gvl` option is disabled by default, you can use bindings effectively in multiple threads.
|
431
|
+
Please be careful: bindings are not thread safe.
|
432
|
+
You should lock all shared data between threads.
|
433
|
+
|
421
434
|
## CI
|
422
435
|
|
423
|
-
See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
|
424
436
|
Please visit [scripts/test-images](scripts/test-images).
|
425
|
-
|
437
|
+
See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
|
438
|
+
You can run this script using many native and cross images.
|
426
439
|
|
427
440
|
## License
|
428
441
|
|
429
|
-
MIT license, see LICENSE and AUTHORS.
|
442
|
+
MIT license, see [LICENSE](LICENSE) and [AUTHORS](AUTHORS).
|
data/ext/extconf.rb
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
|
4
4
|
require "mkmf"
|
5
5
|
|
6
|
+
have_func "rb_thread_call_without_gvl", "ruby/thread.h"
|
7
|
+
|
8
|
+
# Old zstd versions has bug: underlinking against pthreads.
|
9
|
+
# https://bugs.gentoo.org/713940
|
6
10
|
$LDFLAGS << " -pthread" # rubocop:disable Style/GlobalVars
|
7
11
|
|
8
12
|
def require_header(name, types = [])
|
@@ -52,6 +56,7 @@ require_library(
|
|
52
56
|
ZSTD_DStreamOutSize
|
53
57
|
ZSTD_compressStream2
|
54
58
|
ZSTD_decompressStream
|
59
|
+
ZDICT_isError
|
55
60
|
ZDICT_getDictID
|
56
61
|
ZDICT_trainFromBuffer
|
57
62
|
]
|
data/ext/zstds_ext/buffer.c
CHANGED
@@ -12,10 +12,11 @@ VALUE zstds_ext_create_string_buffer(VALUE length)
|
|
12
12
|
return rb_str_new(NULL, NUM2SIZET(length));
|
13
13
|
}
|
14
14
|
|
15
|
-
VALUE zstds_ext_resize_string_buffer(VALUE
|
15
|
+
VALUE zstds_ext_resize_string_buffer(VALUE buffer_args)
|
16
16
|
{
|
17
|
-
VALUE buffer = rb_ary_entry(
|
18
|
-
VALUE length = rb_ary_entry(
|
17
|
+
VALUE buffer = rb_ary_entry(buffer_args, 0);
|
18
|
+
VALUE length = rb_ary_entry(buffer_args, 1);
|
19
|
+
|
19
20
|
return rb_str_resize(buffer, NUM2SIZET(length));
|
20
21
|
}
|
21
22
|
|
data/ext/zstds_ext/buffer.h
CHANGED
@@ -11,12 +11,12 @@ VALUE zstds_ext_create_string_buffer(VALUE length);
|
|
11
11
|
#define ZSTDS_EXT_CREATE_STRING_BUFFER(buffer, length, exception) \
|
12
12
|
VALUE buffer = rb_protect(zstds_ext_create_string_buffer, SIZET2NUM(length), &exception);
|
13
13
|
|
14
|
-
VALUE zstds_ext_resize_string_buffer(VALUE
|
14
|
+
VALUE zstds_ext_resize_string_buffer(VALUE buffer_args);
|
15
15
|
|
16
|
-
#define ZSTDS_EXT_RESIZE_STRING_BUFFER(buffer, length, exception)
|
17
|
-
VALUE
|
18
|
-
buffer
|
19
|
-
RB_GC_GUARD(
|
16
|
+
#define ZSTDS_EXT_RESIZE_STRING_BUFFER(buffer, length, exception) \
|
17
|
+
VALUE buffer_args = rb_ary_new_from_args(2, buffer, SIZET2NUM(length)); \
|
18
|
+
buffer = rb_protect(zstds_ext_resize_string_buffer, buffer_args, &exception); \
|
19
|
+
RB_GC_GUARD(buffer_args);
|
20
20
|
|
21
21
|
void zstds_ext_buffer_exports(VALUE root_module);
|
22
22
|
|
data/ext/zstds_ext/dictionary.c
CHANGED
@@ -9,36 +9,92 @@
|
|
9
9
|
#include "ruby.h"
|
10
10
|
#include "zstds_ext/buffer.h"
|
11
11
|
#include "zstds_ext/error.h"
|
12
|
+
#include "zstds_ext/gvl.h"
|
12
13
|
#include "zstds_ext/macro.h"
|
13
14
|
#include "zstds_ext/option.h"
|
14
15
|
|
15
|
-
|
16
|
+
// -- initialization --
|
17
|
+
|
18
|
+
typedef struct
|
16
19
|
{
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
const char* data;
|
21
|
+
size_t size;
|
22
|
+
} sample_t;
|
23
|
+
|
24
|
+
typedef struct
|
25
|
+
{
|
26
|
+
const sample_t* samples;
|
27
|
+
size_t length;
|
28
|
+
char* buffer;
|
29
|
+
size_t capacity;
|
30
|
+
zstds_result_t result;
|
31
|
+
zstds_ext_result_t ext_result;
|
32
|
+
} train_args_t;
|
33
|
+
|
34
|
+
static inline void* train_wrapper(void* data)
|
35
|
+
{
|
36
|
+
train_args_t* args = data;
|
37
|
+
const sample_t* samples = args->samples;
|
38
|
+
size_t length = args->length;
|
39
|
+
size_t size = 0;
|
40
|
+
|
41
|
+
for (size_t index = 0; index < length; index++) {
|
42
|
+
size += samples[index].size;
|
20
43
|
}
|
21
44
|
|
22
|
-
|
45
|
+
zstds_ext_byte_t* group = malloc(size);
|
46
|
+
if (group == NULL) {
|
47
|
+
args->ext_result = ZSTDS_EXT_ERROR_ALLOCATE_FAILED;
|
48
|
+
return NULL;
|
49
|
+
}
|
50
|
+
|
51
|
+
size_t* sizes = malloc(length * sizeof(size_t));
|
52
|
+
if (sizes == NULL) {
|
53
|
+
free(group);
|
54
|
+
args->ext_result = ZSTDS_EXT_ERROR_ALLOCATE_FAILED;
|
55
|
+
return NULL;
|
56
|
+
}
|
57
|
+
|
58
|
+
size_t offset = 0;
|
59
|
+
|
60
|
+
for (size_t index = 0; index < length; index++) {
|
61
|
+
const sample_t* sample_ptr = &samples[index];
|
62
|
+
size_t sample_size = sample_ptr->size;
|
63
|
+
|
64
|
+
memmove(group + offset, sample_ptr->data, sample_size);
|
65
|
+
offset += sample_size;
|
66
|
+
|
67
|
+
sizes[index] = sample_size;
|
68
|
+
}
|
69
|
+
|
70
|
+
args->result = ZDICT_trainFromBuffer((void*) args->buffer, args->capacity, group, sizes, (unsigned int) length);
|
71
|
+
|
72
|
+
free(group);
|
73
|
+
free(sizes);
|
74
|
+
|
75
|
+
if (ZDICT_isError(args->result)) {
|
76
|
+
args->ext_result = zstds_ext_get_error(ZSTD_getErrorCode(args->result));
|
77
|
+
return NULL;
|
78
|
+
}
|
79
|
+
|
80
|
+
args->ext_result = 0;
|
81
|
+
|
82
|
+
return NULL;
|
23
83
|
}
|
24
84
|
|
25
|
-
VALUE zstds_ext_train_dictionary_buffer(VALUE ZSTDS_EXT_UNUSED(self), VALUE
|
85
|
+
VALUE zstds_ext_train_dictionary_buffer(VALUE ZSTDS_EXT_UNUSED(self), VALUE raw_samples, VALUE options)
|
26
86
|
{
|
27
|
-
Check_Type(
|
87
|
+
Check_Type(raw_samples, T_ARRAY);
|
28
88
|
|
29
|
-
size_t
|
30
|
-
unsigned int samples_length = (unsigned int)RARRAY_LEN(samples);
|
31
|
-
size_t samples_size = 0;
|
89
|
+
size_t length = RARRAY_LEN(raw_samples);
|
32
90
|
|
33
|
-
for (
|
34
|
-
|
35
|
-
Check_Type(sample, T_STRING);
|
36
|
-
|
37
|
-
samples_size += RSTRING_LEN(sample);
|
91
|
+
for (size_t index = 0; index < length; index++) {
|
92
|
+
Check_Type(rb_ary_entry(raw_samples, index), T_STRING);
|
38
93
|
}
|
39
94
|
|
40
95
|
Check_Type(options, T_HASH);
|
41
|
-
|
96
|
+
ZSTDS_EXT_GET_BOOL_OPTION(options, gvl);
|
97
|
+
ZSTDS_EXT_GET_SIZE_OPTION(options, capacity);
|
42
98
|
|
43
99
|
if (capacity == 0) {
|
44
100
|
capacity = ZSTDS_EXT_DEFAULT_DICTIONARY_CAPACITY;
|
@@ -51,42 +107,34 @@ VALUE zstds_ext_train_dictionary_buffer(VALUE ZSTDS_EXT_UNUSED(self), VALUE samp
|
|
51
107
|
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
52
108
|
}
|
53
109
|
|
54
|
-
|
55
|
-
if (
|
110
|
+
sample_t* samples = malloc(sizeof(sample_t) * length);
|
111
|
+
if (samples == NULL) {
|
56
112
|
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
57
113
|
}
|
58
114
|
|
59
|
-
size_t
|
60
|
-
|
61
|
-
|
62
|
-
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
63
|
-
}
|
115
|
+
for (size_t index = 0; index < length; index++) {
|
116
|
+
VALUE raw_sample = rb_ary_entry(raw_samples, index);
|
117
|
+
sample_t* sample = &samples[index];
|
64
118
|
|
65
|
-
|
66
|
-
|
67
|
-
for (sample_index = 0; sample_index < samples_length; sample_index++) {
|
68
|
-
VALUE sample = rb_ary_entry(samples, sample_index);
|
69
|
-
const char* sample_data = RSTRING_PTR(sample);
|
70
|
-
size_t sample_size = RSTRING_LEN(sample);
|
71
|
-
|
72
|
-
memmove(samples_buffer + sample_offset, sample_data, sample_size);
|
73
|
-
sample_offset += sample_size;
|
74
|
-
|
75
|
-
samples_sizes[sample_index] = sample_size;
|
119
|
+
sample->data = RSTRING_PTR(raw_sample);
|
120
|
+
sample->size = RSTRING_LEN(raw_sample);
|
76
121
|
}
|
77
122
|
|
78
|
-
|
79
|
-
|
80
|
-
|
123
|
+
train_args_t args = {
|
124
|
+
.samples = samples,
|
125
|
+
.length = length,
|
126
|
+
.buffer = RSTRING_PTR(buffer),
|
127
|
+
.capacity = capacity,
|
128
|
+
};
|
81
129
|
|
82
|
-
|
83
|
-
free(
|
130
|
+
ZSTDS_EXT_GVL_WRAP(gvl, train_wrapper, &args);
|
131
|
+
free(samples);
|
84
132
|
|
85
|
-
if (
|
86
|
-
zstds_ext_raise_error(
|
133
|
+
if (args.ext_result != 0) {
|
134
|
+
zstds_ext_raise_error(args.ext_result);
|
87
135
|
}
|
88
136
|
|
89
|
-
ZSTDS_EXT_RESIZE_STRING_BUFFER(buffer, result, exception);
|
137
|
+
ZSTDS_EXT_RESIZE_STRING_BUFFER(buffer, args.result, exception);
|
90
138
|
if (exception != 0) {
|
91
139
|
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ALLOCATE_FAILED);
|
92
140
|
}
|
@@ -94,6 +142,20 @@ VALUE zstds_ext_train_dictionary_buffer(VALUE ZSTDS_EXT_UNUSED(self), VALUE samp
|
|
94
142
|
return buffer;
|
95
143
|
}
|
96
144
|
|
145
|
+
// -- other --
|
146
|
+
|
147
|
+
VALUE zstds_ext_get_dictionary_buffer_id(VALUE ZSTDS_EXT_UNUSED(self), VALUE buffer)
|
148
|
+
{
|
149
|
+
unsigned int id = ZDICT_getDictID(RSTRING_PTR(buffer), RSTRING_LEN(buffer));
|
150
|
+
if (id == 0) {
|
151
|
+
zstds_ext_raise_error(ZSTDS_EXT_ERROR_VALIDATE_FAILED);
|
152
|
+
}
|
153
|
+
|
154
|
+
return UINT2NUM(id);
|
155
|
+
}
|
156
|
+
|
157
|
+
// -- exports --
|
158
|
+
|
97
159
|
void zstds_ext_dictionary_exports(VALUE root_module)
|
98
160
|
{
|
99
161
|
VALUE dictionary = rb_define_class_under(root_module, "Dictionary", rb_cObject);
|
data/ext/zstds_ext/dictionary.h
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
|
9
9
|
#define ZSTDS_EXT_DEFAULT_DICTIONARY_CAPACITY (1 << 17); // 128 KB
|
10
10
|
|
11
|
-
VALUE zstds_ext_get_dictionary_buffer_id(VALUE self, VALUE buffer);
|
12
11
|
VALUE zstds_ext_train_dictionary_buffer(VALUE self, VALUE samples, VALUE options);
|
12
|
+
VALUE zstds_ext_get_dictionary_buffer_id(VALUE self, VALUE buffer);
|
13
13
|
|
14
14
|
void zstds_ext_dictionary_exports(VALUE root_module);
|
15
15
|
|
data/ext/zstds_ext/error.c
CHANGED
@@ -40,7 +40,7 @@ zstds_ext_result_t zstds_ext_get_error(ZSTD_ErrorCode error_code)
|
|
40
40
|
}
|
41
41
|
}
|
42
42
|
|
43
|
-
static inline NORETURN(void raise(const char
|
43
|
+
static inline NORETURN(void raise(const char* name, const char* description))
|
44
44
|
{
|
45
45
|
VALUE module = rb_define_module(ZSTDS_EXT_MODULE_NAME);
|
46
46
|
VALUE error = rb_const_get(module, rb_intern(name));
|
data/ext/zstds_ext/error.h
CHANGED
data/ext/zstds_ext/gvl.h
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
// Ruby bindings for zstd library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#if !defined(ZSTDS_EXT_GVL_H)
|
5
|
+
#define ZSTDS_EXT_GVL_H
|
6
|
+
|
7
|
+
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
8
|
+
|
9
|
+
#include "ruby/thread.h"
|
10
|
+
|
11
|
+
#define ZSTDS_EXT_GVL_WRAP(gvl, function, data) \
|
12
|
+
if (gvl) { \
|
13
|
+
function((void*) data); \
|
14
|
+
} else { \
|
15
|
+
rb_thread_call_without_gvl(function, (void*) data, RUBY_UBF_IO, NULL); \
|
16
|
+
}
|
17
|
+
|
18
|
+
#else
|
19
|
+
|
20
|
+
#define ZSTDS_EXT_GVL_WRAP(_gvl, function, data) function((void*) data);
|
21
|
+
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#endif // ZSTDS_EXT_GVL_H
|
data/ext/zstds_ext/io.c
CHANGED
@@ -1,26 +1,29 @@
|
|
1
1
|
// Ruby bindings for zstd library.
|
2
2
|
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
3
|
|
4
|
-
#include "
|
4
|
+
#include "zstds_ext/io.h"
|
5
5
|
|
6
6
|
#include <stdio.h>
|
7
7
|
#include <string.h>
|
8
8
|
#include <zstd.h>
|
9
9
|
|
10
10
|
#include "ruby.h"
|
11
|
+
#include "ruby/io.h"
|
11
12
|
#include "zstds_ext/error.h"
|
12
|
-
#include "zstds_ext/
|
13
|
+
#include "zstds_ext/gvl.h"
|
13
14
|
#include "zstds_ext/macro.h"
|
14
15
|
#include "zstds_ext/option.h"
|
15
16
|
|
16
17
|
// Additional possible results:
|
17
|
-
enum
|
18
|
+
enum
|
19
|
+
{
|
18
20
|
ZSTDS_EXT_FILE_READ_FINISHED = 128
|
19
21
|
};
|
20
22
|
|
21
23
|
// -- file --
|
22
24
|
|
23
|
-
static inline zstds_ext_result_t
|
25
|
+
static inline zstds_ext_result_t
|
26
|
+
read_file(FILE* source_file, zstds_ext_byte_t* source_buffer, size_t* source_length_ptr, size_t source_buffer_length)
|
24
27
|
{
|
25
28
|
size_t read_length = fread(source_buffer, 1, source_buffer_length, source_file);
|
26
29
|
if (read_length == 0 && feof(source_file)) {
|
@@ -36,7 +39,8 @@ static inline zstds_ext_result_t read_file(FILE* source_file, zstds_ext_byte_t*
|
|
36
39
|
return 0;
|
37
40
|
}
|
38
41
|
|
39
|
-
static inline zstds_ext_result_t
|
42
|
+
static inline zstds_ext_result_t
|
43
|
+
write_file(FILE* destination_file, zstds_ext_byte_t* destination_buffer, size_t destination_length)
|
40
44
|
{
|
41
45
|
size_t written_length = fwrite(destination_buffer, 1, destination_length, destination_file);
|
42
46
|
if (written_length != destination_length) {
|
@@ -49,8 +53,10 @@ static inline zstds_ext_result_t write_file(FILE* destination_file, zstds_ext_by
|
|
49
53
|
// -- buffer --
|
50
54
|
|
51
55
|
static inline zstds_ext_result_t create_buffers(
|
52
|
-
zstds_ext_byte_t** source_buffer_ptr,
|
53
|
-
|
56
|
+
zstds_ext_byte_t** source_buffer_ptr,
|
57
|
+
size_t source_buffer_length,
|
58
|
+
zstds_ext_byte_t** destination_buffer_ptr,
|
59
|
+
size_t destination_buffer_length)
|
54
60
|
{
|
55
61
|
zstds_ext_byte_t* source_buffer = malloc(source_buffer_length);
|
56
62
|
if (source_buffer == NULL) {
|
@@ -77,8 +83,10 @@ static inline zstds_ext_result_t create_buffers(
|
|
77
83
|
|
78
84
|
static inline zstds_ext_result_t read_more_source(
|
79
85
|
FILE* source_file,
|
80
|
-
const zstds_ext_byte_t** source_ptr,
|
81
|
-
|
86
|
+
const zstds_ext_byte_t** source_ptr,
|
87
|
+
size_t* source_length_ptr,
|
88
|
+
zstds_ext_byte_t* source_buffer,
|
89
|
+
size_t source_buffer_length)
|
82
90
|
{
|
83
91
|
const zstds_ext_byte_t* source = *source_ptr;
|
84
92
|
size_t source_length = *source_length_ptr;
|
@@ -101,7 +109,9 @@ static inline zstds_ext_result_t read_more_source(
|
|
101
109
|
zstds_ext_byte_t* remaining_source_buffer = source_buffer + source_length;
|
102
110
|
size_t new_source_length;
|
103
111
|
|
104
|
-
zstds_ext_result_t ext_result =
|
112
|
+
zstds_ext_result_t ext_result =
|
113
|
+
read_file(source_file, remaining_source_buffer, &new_source_length, remaining_source_buffer_length);
|
114
|
+
|
105
115
|
if (ext_result != 0) {
|
106
116
|
return ext_result;
|
107
117
|
}
|
@@ -111,42 +121,37 @@ static inline zstds_ext_result_t read_more_source(
|
|
111
121
|
return 0;
|
112
122
|
}
|
113
123
|
|
114
|
-
#define BUFFERED_READ_SOURCE(function, ...)
|
115
|
-
do {
|
116
|
-
bool is_function_called = false;
|
117
|
-
|
118
|
-
while (true) {
|
119
|
-
ext_result = read_more_source(
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
return ext_result;
|
133
|
-
}
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
\
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
ext_result = function(__VA_ARGS__); \
|
146
|
-
if (ext_result != 0) { \
|
147
|
-
return ext_result; \
|
148
|
-
} \
|
149
|
-
} \
|
124
|
+
#define BUFFERED_READ_SOURCE(function, ...) \
|
125
|
+
do { \
|
126
|
+
bool is_function_called = false; \
|
127
|
+
\
|
128
|
+
while (true) { \
|
129
|
+
ext_result = read_more_source(source_file, &source, &source_length, source_buffer, source_buffer_length); \
|
130
|
+
if (ext_result == ZSTDS_EXT_FILE_READ_FINISHED) { \
|
131
|
+
if (source_length != 0) { \
|
132
|
+
/* ZSTD won't provide any remainder by design. */ \
|
133
|
+
return ZSTDS_EXT_ERROR_READ_IO; \
|
134
|
+
} \
|
135
|
+
break; \
|
136
|
+
} else if (ext_result != 0) { \
|
137
|
+
return ext_result; \
|
138
|
+
} \
|
139
|
+
\
|
140
|
+
ext_result = function(__VA_ARGS__); \
|
141
|
+
if (ext_result != 0) { \
|
142
|
+
return ext_result; \
|
143
|
+
} \
|
144
|
+
\
|
145
|
+
is_function_called = true; \
|
146
|
+
} \
|
147
|
+
\
|
148
|
+
if (!is_function_called) { \
|
149
|
+
/* Function should be called at least once. */ \
|
150
|
+
ext_result = function(__VA_ARGS__); \
|
151
|
+
if (ext_result != 0) { \
|
152
|
+
return ext_result; \
|
153
|
+
} \
|
154
|
+
} \
|
150
155
|
} while (false);
|
151
156
|
|
152
157
|
// Algorithm has written data into destination buffer.
|
@@ -155,7 +160,9 @@ static inline zstds_ext_result_t read_more_source(
|
|
155
160
|
|
156
161
|
static inline zstds_ext_result_t flush_destination_buffer(
|
157
162
|
FILE* destination_file,
|
158
|
-
zstds_ext_byte_t* destination_buffer,
|
163
|
+
zstds_ext_byte_t* destination_buffer,
|
164
|
+
size_t* destination_length_ptr,
|
165
|
+
size_t destination_buffer_length)
|
159
166
|
{
|
160
167
|
if (*destination_length_ptr == 0) {
|
161
168
|
// We want to write more data at once, than buffer has.
|
@@ -172,7 +179,8 @@ static inline zstds_ext_result_t flush_destination_buffer(
|
|
172
179
|
return 0;
|
173
180
|
}
|
174
181
|
|
175
|
-
static inline zstds_ext_result_t
|
182
|
+
static inline zstds_ext_result_t
|
183
|
+
write_remaining_destination(FILE* destination_file, zstds_ext_byte_t* destination_buffer, size_t destination_length)
|
176
184
|
{
|
177
185
|
if (destination_length == 0) {
|
178
186
|
return 0;
|
@@ -194,39 +202,57 @@ static inline zstds_ext_result_t write_remaining_destination(FILE* destination_f
|
|
194
202
|
zstds_ext_raise_error(ZSTDS_EXT_ERROR_ACCESS_IO); \
|
195
203
|
}
|
196
204
|
|
197
|
-
// -- compress --
|
205
|
+
// -- buffered compress --
|
206
|
+
|
207
|
+
typedef struct
|
208
|
+
{
|
209
|
+
ZSTD_CCtx* ctx;
|
210
|
+
ZSTD_inBuffer* in_buffer_ptr;
|
211
|
+
ZSTD_outBuffer* out_buffer_ptr;
|
212
|
+
zstds_result_t result;
|
213
|
+
} compress_args_t;
|
214
|
+
|
215
|
+
static inline void* compress_wrapper(void* data)
|
216
|
+
{
|
217
|
+
compress_args_t* args = data;
|
218
|
+
|
219
|
+
args->result = ZSTD_compressStream2(args->ctx, args->out_buffer_ptr, args->in_buffer_ptr, ZSTD_e_continue);
|
220
|
+
|
221
|
+
return NULL;
|
222
|
+
}
|
198
223
|
|
199
224
|
static inline zstds_ext_result_t buffered_compress(
|
200
225
|
ZSTD_CCtx* ctx,
|
201
|
-
const zstds_ext_byte_t** source_ptr,
|
202
|
-
|
226
|
+
const zstds_ext_byte_t** source_ptr,
|
227
|
+
size_t* source_length_ptr,
|
228
|
+
FILE* destination_file,
|
229
|
+
zstds_ext_byte_t* destination_buffer,
|
230
|
+
size_t* destination_length_ptr,
|
231
|
+
size_t destination_buffer_length,
|
232
|
+
bool gvl)
|
203
233
|
{
|
204
|
-
zstds_result_t result;
|
205
234
|
zstds_ext_result_t ext_result;
|
206
|
-
|
207
|
-
|
208
|
-
in_buffer.src = *source_ptr;
|
209
|
-
in_buffer.size = *source_length_ptr;
|
210
|
-
in_buffer.pos = 0;
|
211
|
-
|
212
|
-
ZSTD_outBuffer out_buffer;
|
235
|
+
ZSTD_inBuffer in_buffer = {.src = *source_ptr, .size = *source_length_ptr, .pos = 0};
|
236
|
+
compress_args_t args = {.ctx = ctx, .in_buffer_ptr = &in_buffer};
|
213
237
|
|
214
238
|
while (true) {
|
215
|
-
out_buffer
|
216
|
-
|
217
|
-
|
239
|
+
ZSTD_outBuffer out_buffer = {
|
240
|
+
.dst = destination_buffer + *destination_length_ptr,
|
241
|
+
.size = destination_buffer_length - *destination_length_ptr,
|
242
|
+
.pos = 0};
|
218
243
|
|
219
|
-
|
220
|
-
|
221
|
-
|
244
|
+
args.out_buffer_ptr = &out_buffer;
|
245
|
+
|
246
|
+
ZSTDS_EXT_GVL_WRAP(gvl, compress_wrapper, &args);
|
247
|
+
if (ZSTD_isError(args.result)) {
|
248
|
+
return zstds_ext_get_error(ZSTD_getErrorCode(args.result));
|
222
249
|
}
|
223
250
|
|
224
251
|
*destination_length_ptr += out_buffer.pos;
|
225
252
|
|
226
253
|
if (*destination_length_ptr == destination_buffer_length) {
|
227
254
|
ext_result = flush_destination_buffer(
|
228
|
-
destination_file,
|
229
|
-
destination_buffer, destination_length_ptr, destination_buffer_length);
|
255
|
+
destination_file, destination_buffer, destination_length_ptr, destination_buffer_length);
|
230
256
|
|
231
257
|
if (ext_result != 0) {
|
232
258
|
return ext_result;
|
@@ -244,36 +270,55 @@ static inline zstds_ext_result_t buffered_compress(
|
|
244
270
|
return 0;
|
245
271
|
}
|
246
272
|
|
247
|
-
|
248
|
-
|
249
|
-
|
273
|
+
// -- buffered compressor finish --
|
274
|
+
|
275
|
+
typedef struct
|
250
276
|
{
|
251
|
-
|
252
|
-
|
277
|
+
ZSTD_CCtx* ctx;
|
278
|
+
ZSTD_inBuffer* in_buffer_ptr;
|
279
|
+
ZSTD_outBuffer* out_buffer_ptr;
|
280
|
+
zstds_result_t result;
|
281
|
+
} compressor_finish_args_t;
|
253
282
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
in_buffer.pos = 0;
|
283
|
+
static inline void* compressor_finish_wrapper(void* data)
|
284
|
+
{
|
285
|
+
compressor_finish_args_t* args = data;
|
258
286
|
|
259
|
-
|
287
|
+
args->result = ZSTD_compressStream2(args->ctx, args->out_buffer_ptr, args->in_buffer_ptr, ZSTD_e_end);
|
288
|
+
|
289
|
+
return NULL;
|
290
|
+
}
|
291
|
+
|
292
|
+
static inline zstds_ext_result_t buffered_compressor_finish(
|
293
|
+
ZSTD_CCtx* ctx,
|
294
|
+
FILE* destination_file,
|
295
|
+
zstds_ext_byte_t* destination_buffer,
|
296
|
+
size_t* destination_length_ptr,
|
297
|
+
size_t destination_buffer_length,
|
298
|
+
bool gvl)
|
299
|
+
{
|
300
|
+
zstds_ext_result_t ext_result;
|
301
|
+
ZSTD_inBuffer in_buffer = {in_buffer.src = NULL, in_buffer.size = 0, in_buffer.pos = 0};
|
302
|
+
compressor_finish_args_t args = {.ctx = ctx, .in_buffer_ptr = &in_buffer};
|
260
303
|
|
261
304
|
while (true) {
|
262
|
-
out_buffer
|
263
|
-
|
264
|
-
|
305
|
+
ZSTD_outBuffer out_buffer = {
|
306
|
+
out_buffer.dst = destination_buffer + *destination_length_ptr,
|
307
|
+
out_buffer.size = destination_buffer_length - *destination_length_ptr,
|
308
|
+
out_buffer.pos = 0};
|
265
309
|
|
266
|
-
|
267
|
-
|
268
|
-
|
310
|
+
args.out_buffer_ptr = &out_buffer;
|
311
|
+
|
312
|
+
ZSTDS_EXT_GVL_WRAP(gvl, compressor_finish_wrapper, &args);
|
313
|
+
if (ZSTD_isError(args.result)) {
|
314
|
+
return zstds_ext_get_error(ZSTD_getErrorCode(args.result));
|
269
315
|
}
|
270
316
|
|
271
317
|
*destination_length_ptr += out_buffer.pos;
|
272
318
|
|
273
|
-
if (result != 0) {
|
319
|
+
if (args.result != 0) {
|
274
320
|
ext_result = flush_destination_buffer(
|
275
|
-
destination_file,
|
276
|
-
destination_buffer, destination_length_ptr, destination_buffer_length);
|
321
|
+
destination_file, destination_buffer, destination_length_ptr, destination_buffer_length);
|
277
322
|
|
278
323
|
if (ext_result != 0) {
|
279
324
|
return ext_result;
|
@@ -288,13 +333,19 @@ static inline zstds_ext_result_t buffered_compressor_finish(
|
|
288
333
|
return 0;
|
289
334
|
}
|
290
335
|
|
336
|
+
// -- compress --
|
337
|
+
|
291
338
|
static inline zstds_ext_result_t compress(
|
292
|
-
ZSTD_CCtx*
|
293
|
-
FILE*
|
294
|
-
|
339
|
+
ZSTD_CCtx* ctx,
|
340
|
+
FILE* source_file,
|
341
|
+
zstds_ext_byte_t* source_buffer,
|
342
|
+
size_t source_buffer_length,
|
343
|
+
FILE* destination_file,
|
344
|
+
zstds_ext_byte_t* destination_buffer,
|
345
|
+
size_t destination_buffer_length,
|
346
|
+
bool gvl)
|
295
347
|
{
|
296
|
-
zstds_ext_result_t
|
297
|
-
|
348
|
+
zstds_ext_result_t ext_result;
|
298
349
|
const zstds_ext_byte_t* source = source_buffer;
|
299
350
|
size_t source_length = 0;
|
300
351
|
size_t destination_length = 0;
|
@@ -302,12 +353,16 @@ static inline zstds_ext_result_t compress(
|
|
302
353
|
BUFFERED_READ_SOURCE(
|
303
354
|
buffered_compress,
|
304
355
|
ctx,
|
305
|
-
&source,
|
306
|
-
|
356
|
+
&source,
|
357
|
+
&source_length,
|
358
|
+
destination_file,
|
359
|
+
destination_buffer,
|
360
|
+
&destination_length,
|
361
|
+
destination_buffer_length,
|
362
|
+
gvl);
|
307
363
|
|
308
364
|
ext_result = buffered_compressor_finish(
|
309
|
-
ctx,
|
310
|
-
destination_file, destination_buffer, &destination_length, destination_buffer_length);
|
365
|
+
ctx, destination_file, destination_buffer, &destination_length, destination_buffer_length, gvl);
|
311
366
|
|
312
367
|
if (ext_result != 0) {
|
313
368
|
return ext_result;
|
@@ -321,9 +376,10 @@ VALUE zstds_ext_compress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE de
|
|
321
376
|
GET_FILE(source);
|
322
377
|
GET_FILE(destination);
|
323
378
|
Check_Type(options, T_HASH);
|
379
|
+
ZSTDS_EXT_GET_SIZE_OPTION(options, source_buffer_length);
|
380
|
+
ZSTDS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
381
|
+
ZSTDS_EXT_GET_BOOL_OPTION(options, gvl);
|
324
382
|
ZSTDS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
325
|
-
ZSTDS_EXT_GET_BUFFER_LENGTH_OPTION(options, source_buffer_length);
|
326
|
-
ZSTDS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
327
383
|
|
328
384
|
ZSTD_CCtx* ctx = ZSTD_createCCtx();
|
329
385
|
if (ctx == NULL) {
|
@@ -346,10 +402,7 @@ VALUE zstds_ext_compress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE de
|
|
346
402
|
zstds_ext_byte_t* source_buffer;
|
347
403
|
zstds_ext_byte_t* destination_buffer;
|
348
404
|
|
349
|
-
ext_result = create_buffers(
|
350
|
-
&source_buffer, source_buffer_length,
|
351
|
-
&destination_buffer, destination_buffer_length);
|
352
|
-
|
405
|
+
ext_result = create_buffers(&source_buffer, source_buffer_length, &destination_buffer, destination_buffer_length);
|
353
406
|
if (ext_result != 0) {
|
354
407
|
ZSTD_freeCCtx(ctx);
|
355
408
|
zstds_ext_raise_error(ext_result);
|
@@ -357,8 +410,13 @@ VALUE zstds_ext_compress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE de
|
|
357
410
|
|
358
411
|
ext_result = compress(
|
359
412
|
ctx,
|
360
|
-
source_file,
|
361
|
-
|
413
|
+
source_file,
|
414
|
+
source_buffer,
|
415
|
+
source_buffer_length,
|
416
|
+
destination_file,
|
417
|
+
destination_buffer,
|
418
|
+
destination_buffer_length,
|
419
|
+
gvl);
|
362
420
|
|
363
421
|
free(source_buffer);
|
364
422
|
free(destination_buffer);
|
@@ -374,39 +432,57 @@ VALUE zstds_ext_compress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE de
|
|
374
432
|
return Qnil;
|
375
433
|
}
|
376
434
|
|
377
|
-
// -- decompress --
|
435
|
+
// -- buffered decompress --
|
436
|
+
|
437
|
+
typedef struct
|
438
|
+
{
|
439
|
+
ZSTD_DCtx* ctx;
|
440
|
+
ZSTD_inBuffer* in_buffer_ptr;
|
441
|
+
ZSTD_outBuffer* out_buffer_ptr;
|
442
|
+
zstds_result_t result;
|
443
|
+
} decompress_args_t;
|
444
|
+
|
445
|
+
static inline void* decompress_wrapper(void* data)
|
446
|
+
{
|
447
|
+
decompress_args_t* args = data;
|
448
|
+
|
449
|
+
args->result = ZSTD_decompressStream(args->ctx, args->out_buffer_ptr, args->in_buffer_ptr);
|
450
|
+
|
451
|
+
return NULL;
|
452
|
+
}
|
378
453
|
|
379
454
|
static inline zstds_ext_result_t buffered_decompress(
|
380
455
|
ZSTD_DCtx* ctx,
|
381
|
-
const zstds_ext_byte_t** source_ptr,
|
382
|
-
|
456
|
+
const zstds_ext_byte_t** source_ptr,
|
457
|
+
size_t* source_length_ptr,
|
458
|
+
FILE* destination_file,
|
459
|
+
zstds_ext_byte_t* destination_buffer,
|
460
|
+
size_t* destination_length_ptr,
|
461
|
+
size_t destination_buffer_length,
|
462
|
+
bool gvl)
|
383
463
|
{
|
384
|
-
zstds_result_t result;
|
385
464
|
zstds_ext_result_t ext_result;
|
386
|
-
|
387
|
-
|
388
|
-
in_buffer.src = *source_ptr;
|
389
|
-
in_buffer.size = *source_length_ptr;
|
390
|
-
in_buffer.pos = 0;
|
391
|
-
|
392
|
-
ZSTD_outBuffer out_buffer;
|
465
|
+
ZSTD_inBuffer in_buffer = {.src = *source_ptr, .size = *source_length_ptr, .pos = 0};
|
466
|
+
decompress_args_t args = {.ctx = ctx, .in_buffer_ptr = &in_buffer};
|
393
467
|
|
394
468
|
while (true) {
|
395
|
-
out_buffer
|
396
|
-
|
397
|
-
|
469
|
+
ZSTD_outBuffer out_buffer = {
|
470
|
+
.dst = destination_buffer + *destination_length_ptr,
|
471
|
+
.size = destination_buffer_length - *destination_length_ptr,
|
472
|
+
.pos = 0};
|
473
|
+
|
474
|
+
args.out_buffer_ptr = &out_buffer;
|
398
475
|
|
399
|
-
|
400
|
-
if (ZSTD_isError(result)) {
|
401
|
-
return zstds_ext_get_error(ZSTD_getErrorCode(result));
|
476
|
+
ZSTDS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
|
477
|
+
if (ZSTD_isError(args.result)) {
|
478
|
+
return zstds_ext_get_error(ZSTD_getErrorCode(args.result));
|
402
479
|
}
|
403
480
|
|
404
481
|
*destination_length_ptr += out_buffer.pos;
|
405
482
|
|
406
483
|
if (*destination_length_ptr == destination_buffer_length) {
|
407
484
|
ext_result = flush_destination_buffer(
|
408
|
-
destination_file,
|
409
|
-
destination_buffer, destination_length_ptr, destination_buffer_length);
|
485
|
+
destination_file, destination_buffer, destination_length_ptr, destination_buffer_length);
|
410
486
|
|
411
487
|
if (ext_result != 0) {
|
412
488
|
return ext_result;
|
@@ -424,13 +500,19 @@ static inline zstds_ext_result_t buffered_decompress(
|
|
424
500
|
return 0;
|
425
501
|
}
|
426
502
|
|
503
|
+
// -- decompress --
|
504
|
+
|
427
505
|
static inline zstds_ext_result_t decompress(
|
428
|
-
ZSTD_DCtx*
|
429
|
-
FILE*
|
430
|
-
|
506
|
+
ZSTD_DCtx* ctx,
|
507
|
+
FILE* source_file,
|
508
|
+
zstds_ext_byte_t* source_buffer,
|
509
|
+
size_t source_buffer_length,
|
510
|
+
FILE* destination_file,
|
511
|
+
zstds_ext_byte_t* destination_buffer,
|
512
|
+
size_t destination_buffer_length,
|
513
|
+
bool gvl)
|
431
514
|
{
|
432
|
-
zstds_ext_result_t
|
433
|
-
|
515
|
+
zstds_ext_result_t ext_result;
|
434
516
|
const zstds_ext_byte_t* source = source_buffer;
|
435
517
|
size_t source_length = 0;
|
436
518
|
size_t destination_length = 0;
|
@@ -438,8 +520,13 @@ static inline zstds_ext_result_t decompress(
|
|
438
520
|
BUFFERED_READ_SOURCE(
|
439
521
|
buffered_decompress,
|
440
522
|
ctx,
|
441
|
-
&source,
|
442
|
-
|
523
|
+
&source,
|
524
|
+
&source_length,
|
525
|
+
destination_file,
|
526
|
+
destination_buffer,
|
527
|
+
&destination_length,
|
528
|
+
destination_buffer_length,
|
529
|
+
gvl);
|
443
530
|
|
444
531
|
return write_remaining_destination(destination_file, destination_buffer, destination_length);
|
445
532
|
}
|
@@ -449,9 +536,10 @@ VALUE zstds_ext_decompress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE
|
|
449
536
|
GET_FILE(source);
|
450
537
|
GET_FILE(destination);
|
451
538
|
Check_Type(options, T_HASH);
|
539
|
+
ZSTDS_EXT_GET_SIZE_OPTION(options, source_buffer_length);
|
540
|
+
ZSTDS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
541
|
+
ZSTDS_EXT_GET_BOOL_OPTION(options, gvl);
|
452
542
|
ZSTDS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
453
|
-
ZSTDS_EXT_GET_BUFFER_LENGTH_OPTION(options, source_buffer_length);
|
454
|
-
ZSTDS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
455
543
|
|
456
544
|
ZSTD_DCtx* ctx = ZSTD_createDCtx();
|
457
545
|
if (ctx == NULL) {
|
@@ -474,10 +562,7 @@ VALUE zstds_ext_decompress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE
|
|
474
562
|
zstds_ext_byte_t* source_buffer;
|
475
563
|
zstds_ext_byte_t* destination_buffer;
|
476
564
|
|
477
|
-
ext_result = create_buffers(
|
478
|
-
&source_buffer, source_buffer_length,
|
479
|
-
&destination_buffer, destination_buffer_length);
|
480
|
-
|
565
|
+
ext_result = create_buffers(&source_buffer, source_buffer_length, &destination_buffer, destination_buffer_length);
|
481
566
|
if (ext_result != 0) {
|
482
567
|
ZSTD_freeDCtx(ctx);
|
483
568
|
zstds_ext_raise_error(ext_result);
|
@@ -485,8 +570,13 @@ VALUE zstds_ext_decompress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE
|
|
485
570
|
|
486
571
|
ext_result = decompress(
|
487
572
|
ctx,
|
488
|
-
source_file,
|
489
|
-
|
573
|
+
source_file,
|
574
|
+
source_buffer,
|
575
|
+
source_buffer_length,
|
576
|
+
destination_file,
|
577
|
+
destination_buffer,
|
578
|
+
destination_buffer_length,
|
579
|
+
gvl);
|
490
580
|
|
491
581
|
free(source_buffer);
|
492
582
|
free(destination_buffer);
|
@@ -502,6 +592,8 @@ VALUE zstds_ext_decompress_io(VALUE ZSTDS_EXT_UNUSED(self), VALUE source, VALUE
|
|
502
592
|
return Qnil;
|
503
593
|
}
|
504
594
|
|
595
|
+
// -- exports --
|
596
|
+
|
505
597
|
void zstds_ext_io_exports(VALUE root_module)
|
506
598
|
{
|
507
599
|
rb_define_module_function(root_module, "_native_compress_io", RUBY_METHOD_FUNC(zstds_ext_compress_io), 3);
|