ruby-zstds 1.0.3 → 1.1.1
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 +133 -170
- data/ext/extconf.rb +13 -1
- 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 +12 -12
- 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/file.rb +6 -2
- data/lib/zstds/option.rb +18 -7
- data/lib/zstds/stream/abstract.rb +6 -9
- data/lib/zstds/stream/raw/abstract.rb +6 -2
- data/lib/zstds/stream/raw/compressor.rb +3 -7
- data/lib/zstds/stream/raw/decompressor.rb +1 -5
- data/lib/zstds/stream/reader.rb +72 -52
- data/lib/zstds/stream/reader_helpers.rb +1 -1
- data/lib/zstds/stream/writer.rb +9 -4
- data/lib/zstds/stream/writer_helpers.rb +3 -2
- data/lib/zstds/validation.rb +4 -2
- data/lib/zstds/version.rb +1 -1
- metadata +62 -19
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
|
]
|
@@ -75,7 +80,14 @@ $srcs = %w[
|
|
75
80
|
.map { |name| "src/#{extension_name}/#{name}.c" }
|
76
81
|
.freeze
|
77
82
|
|
78
|
-
|
83
|
+
# Removing library duplicates.
|
84
|
+
$libs = $libs.split(%r{\s})
|
85
|
+
.reject(&:empty?)
|
86
|
+
.sort
|
87
|
+
.uniq
|
88
|
+
.join " "
|
89
|
+
|
90
|
+
if ENV["CI"]
|
79
91
|
$CFLAGS << " --coverage"
|
80
92
|
$LDFLAGS << " --coverage"
|
81
93
|
end
|
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
|
43
|
+
static inline NORETURN(void raise_error(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));
|
@@ -51,30 +51,30 @@ void zstds_ext_raise_error(zstds_ext_result_t ext_result)
|
|
51
51
|
{
|
52
52
|
switch (ext_result) {
|
53
53
|
case ZSTDS_EXT_ERROR_ALLOCATE_FAILED:
|
54
|
-
|
54
|
+
raise_error("AllocateError", "allocate error");
|
55
55
|
case ZSTDS_EXT_ERROR_VALIDATE_FAILED:
|
56
|
-
|
56
|
+
raise_error("ValidateError", "validate error");
|
57
57
|
|
58
58
|
case ZSTDS_EXT_ERROR_USED_AFTER_CLOSE:
|
59
|
-
|
59
|
+
raise_error("UsedAfterCloseError", "used after closed");
|
60
60
|
case ZSTDS_EXT_ERROR_NOT_ENOUGH_SOURCE_BUFFER:
|
61
|
-
|
61
|
+
raise_error("NotEnoughSourceBufferError", "not enough source buffer");
|
62
62
|
case ZSTDS_EXT_ERROR_NOT_ENOUGH_DESTINATION_BUFFER:
|
63
|
-
|
63
|
+
raise_error("NotEnoughDestinationBufferError", "not enough destination buffer");
|
64
64
|
case ZSTDS_EXT_ERROR_DECOMPRESSOR_CORRUPTED_SOURCE:
|
65
|
-
|
65
|
+
raise_error("DecompressorCorruptedSourceError", "decompressor received corrupted source");
|
66
66
|
case ZSTDS_EXT_ERROR_CORRUPTED_DICTIONARY:
|
67
|
-
|
67
|
+
raise_error("CorruptedDictionaryError", "corrupted dictionary");
|
68
68
|
|
69
69
|
case ZSTDS_EXT_ERROR_ACCESS_IO:
|
70
|
-
|
70
|
+
raise_error("AccessIOError", "failed to access IO");
|
71
71
|
case ZSTDS_EXT_ERROR_READ_IO:
|
72
|
-
|
72
|
+
raise_error("ReadIOError", "failed to read IO");
|
73
73
|
case ZSTDS_EXT_ERROR_WRITE_IO:
|
74
|
-
|
74
|
+
raise_error("WriteIOError", "failed to write IO");
|
75
75
|
|
76
76
|
default:
|
77
77
|
// ZSTDS_EXT_ERROR_UNEXPECTED
|
78
|
-
|
78
|
+
raise_error("UnexpectedError", "unexpected error");
|
79
79
|
}
|
80
80
|
}
|
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);
|