ruby-brs 1.1.4 → 1.3.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 +86 -46
- data/ext/brs_ext/buffer.c +21 -9
- data/ext/brs_ext/buffer.h +7 -7
- data/ext/brs_ext/error.c +11 -15
- data/ext/brs_ext/error.h +2 -1
- data/ext/brs_ext/gvl.h +24 -0
- data/ext/brs_ext/io.c +240 -123
- data/ext/brs_ext/main.c +4 -1
- data/ext/brs_ext/option.c +54 -33
- data/ext/brs_ext/option.h +41 -29
- data/ext/brs_ext/stream/compressor.c +118 -54
- data/ext/brs_ext/stream/compressor.h +4 -1
- data/ext/brs_ext/stream/decompressor.c +54 -25
- data/ext/brs_ext/stream/decompressor.h +4 -1
- data/ext/brs_ext/string.c +118 -65
- data/ext/extconf.rb +90 -10
- data/lib/brs/file.rb +2 -2
- data/lib/brs/option.rb +36 -4
- data/lib/brs/stream/abstract.rb +5 -3
- data/lib/brs/stream/reader.rb +3 -2
- data/lib/brs/stream/reader_helpers.rb +1 -1
- data/lib/brs/validation.rb +3 -1
- data/lib/brs/version.rb +1 -1
- metadata +74 -17
@@ -3,12 +3,12 @@
|
|
3
3
|
|
4
4
|
#include "brs_ext/stream/decompressor.h"
|
5
5
|
|
6
|
-
#include <brotli/decode.h>
|
7
|
-
|
8
6
|
#include "brs_ext/buffer.h"
|
9
7
|
#include "brs_ext/error.h"
|
8
|
+
#include "brs_ext/gvl.h"
|
10
9
|
#include "brs_ext/option.h"
|
11
|
-
|
10
|
+
|
11
|
+
// -- initialization --
|
12
12
|
|
13
13
|
static void free_decompressor(brs_ext_decompressor_t* decompressor_ptr)
|
14
14
|
{
|
@@ -28,7 +28,6 @@ static void free_decompressor(brs_ext_decompressor_t* decompressor_ptr)
|
|
28
28
|
VALUE brs_ext_allocate_decompressor(VALUE klass)
|
29
29
|
{
|
30
30
|
brs_ext_decompressor_t* decompressor_ptr;
|
31
|
-
|
32
31
|
VALUE self = Data_Make_Struct(klass, brs_ext_decompressor_t, NULL, free_decompressor, decompressor_ptr);
|
33
32
|
|
34
33
|
decompressor_ptr->state_ptr = NULL;
|
@@ -48,8 +47,9 @@ VALUE brs_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
48
47
|
{
|
49
48
|
GET_DECOMPRESSOR(self);
|
50
49
|
Check_Type(options, T_HASH);
|
50
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
51
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
51
52
|
BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
52
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
53
53
|
|
54
54
|
BrotliDecoderState* state_ptr = BrotliDecoderCreateInstance(NULL, NULL, NULL);
|
55
55
|
if (state_ptr == NULL) {
|
@@ -77,49 +77,75 @@ VALUE brs_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
77
77
|
decompressor_ptr->destination_buffer_length = destination_buffer_length;
|
78
78
|
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
79
79
|
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
80
|
+
decompressor_ptr->gvl = gvl;
|
80
81
|
|
81
82
|
return Qnil;
|
82
83
|
}
|
83
84
|
|
85
|
+
// -- decompress --
|
86
|
+
|
84
87
|
#define DO_NOT_USE_AFTER_CLOSE(decompressor_ptr) \
|
85
88
|
if (decompressor_ptr->state_ptr == NULL || decompressor_ptr->destination_buffer == NULL) { \
|
86
89
|
brs_ext_raise_error(BRS_EXT_ERROR_USED_AFTER_CLOSE); \
|
87
90
|
}
|
88
91
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
const
|
93
|
-
size_t
|
94
|
-
|
95
|
-
|
92
|
+
typedef struct
|
93
|
+
{
|
94
|
+
brs_ext_decompressor_t* decompressor_ptr;
|
95
|
+
const brs_ext_byte_t* remaining_source;
|
96
|
+
size_t* remaining_source_length_ptr;
|
97
|
+
BrotliDecoderResult result;
|
98
|
+
} decompress_args_t;
|
99
|
+
|
100
|
+
static inline void* decompress_wrapper(void* data)
|
101
|
+
{
|
102
|
+
decompress_args_t* args = data;
|
103
|
+
brs_ext_decompressor_t* decompressor_ptr = args->decompressor_ptr;
|
104
|
+
|
105
|
+
args->result = BrotliDecoderDecompressStream(
|
106
|
+
decompressor_ptr->state_ptr,
|
107
|
+
args->remaining_source_length_ptr,
|
108
|
+
&args->remaining_source,
|
109
|
+
&decompressor_ptr->remaining_destination_buffer_length,
|
110
|
+
&decompressor_ptr->remaining_destination_buffer,
|
111
|
+
NULL);
|
112
|
+
|
113
|
+
return NULL;
|
114
|
+
}
|
96
115
|
|
97
116
|
VALUE brs_ext_decompress(VALUE self, VALUE source_value)
|
98
117
|
{
|
99
118
|
GET_DECOMPRESSOR(self);
|
100
119
|
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
101
|
-
|
120
|
+
Check_Type(source_value, T_STRING);
|
102
121
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
122
|
+
const char* source = RSTRING_PTR(source_value);
|
123
|
+
size_t source_length = RSTRING_LEN(source_value);
|
124
|
+
const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
|
125
|
+
size_t remaining_source_length = source_length;
|
126
|
+
|
127
|
+
decompress_args_t args = {
|
128
|
+
.decompressor_ptr = decompressor_ptr,
|
129
|
+
.remaining_source = remaining_source,
|
130
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
131
|
+
|
132
|
+
BRS_EXT_GVL_WRAP(decompressor_ptr->gvl, decompress_wrapper, &args);
|
108
133
|
|
109
134
|
if (
|
110
|
-
result != BROTLI_DECODER_RESULT_SUCCESS &&
|
111
|
-
result !=
|
112
|
-
result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
135
|
+
args.result != BROTLI_DECODER_RESULT_SUCCESS && args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT &&
|
136
|
+
args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
113
137
|
BrotliDecoderErrorCode error_code = BrotliDecoderGetErrorCode(decompressor_ptr->state_ptr);
|
114
138
|
brs_ext_raise_error(brs_ext_get_decompressor_error(error_code));
|
115
139
|
}
|
116
140
|
|
117
141
|
VALUE bytes_read = SIZET2NUM(source_length - remaining_source_length);
|
118
|
-
VALUE needs_more_destination = result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT ? Qtrue : Qfalse;
|
142
|
+
VALUE needs_more_destination = args.result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT ? Qtrue : Qfalse;
|
119
143
|
|
120
144
|
return rb_ary_new_from_args(2, bytes_read, needs_more_destination);
|
121
145
|
}
|
122
146
|
|
147
|
+
// -- other --
|
148
|
+
|
123
149
|
VALUE brs_ext_decompressor_read_result(VALUE self)
|
124
150
|
{
|
125
151
|
GET_DECOMPRESSOR(self);
|
@@ -129,10 +155,9 @@ VALUE brs_ext_decompressor_read_result(VALUE self)
|
|
129
155
|
size_t destination_buffer_length = decompressor_ptr->destination_buffer_length;
|
130
156
|
size_t remaining_destination_buffer_length = decompressor_ptr->remaining_destination_buffer_length;
|
131
157
|
|
132
|
-
const char* result = (const char*)destination_buffer;
|
158
|
+
const char* result = (const char*) destination_buffer;
|
133
159
|
size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
|
134
|
-
|
135
|
-
VALUE result_value = rb_str_new(result, result_length);
|
160
|
+
VALUE result_value = rb_str_new(result, result_length);
|
136
161
|
|
137
162
|
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
138
163
|
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
@@ -140,6 +165,8 @@ VALUE brs_ext_decompressor_read_result(VALUE self)
|
|
140
165
|
return result_value;
|
141
166
|
}
|
142
167
|
|
168
|
+
// -- cleanup --
|
169
|
+
|
143
170
|
VALUE brs_ext_decompressor_close(VALUE self)
|
144
171
|
{
|
145
172
|
GET_DECOMPRESSOR(self);
|
@@ -165,6 +192,8 @@ VALUE brs_ext_decompressor_close(VALUE self)
|
|
165
192
|
return Qnil;
|
166
193
|
}
|
167
194
|
|
195
|
+
// -- exports --
|
196
|
+
|
168
197
|
void brs_ext_decompressor_exports(VALUE root_module)
|
169
198
|
{
|
170
199
|
VALUE module = rb_define_module_under(root_module, "Stream");
|
@@ -5,17 +5,20 @@
|
|
5
5
|
#define BRS_EXT_STREAM_DECOMPRESSOR_H
|
6
6
|
|
7
7
|
#include <brotli/decode.h>
|
8
|
+
#include <stdbool.h>
|
8
9
|
#include <stdlib.h>
|
9
10
|
|
10
11
|
#include "brs_ext/common.h"
|
11
12
|
#include "ruby.h"
|
12
13
|
|
13
|
-
typedef struct
|
14
|
+
typedef struct
|
15
|
+
{
|
14
16
|
BrotliDecoderState* state_ptr;
|
15
17
|
brs_ext_byte_t* destination_buffer;
|
16
18
|
size_t destination_buffer_length;
|
17
19
|
brs_ext_byte_t* remaining_destination_buffer;
|
18
20
|
size_t remaining_destination_buffer_length;
|
21
|
+
bool gvl;
|
19
22
|
} brs_ext_decompressor_t;
|
20
23
|
|
21
24
|
VALUE brs_ext_allocate_decompressor(VALUE klass);
|
data/ext/brs_ext/string.c
CHANGED
@@ -10,15 +10,17 @@
|
|
10
10
|
|
11
11
|
#include "brs_ext/buffer.h"
|
12
12
|
#include "brs_ext/error.h"
|
13
|
+
#include "brs_ext/gvl.h"
|
13
14
|
#include "brs_ext/macro.h"
|
14
15
|
#include "brs_ext/option.h"
|
15
|
-
#include "ruby.h"
|
16
16
|
|
17
17
|
// -- buffer --
|
18
18
|
|
19
19
|
static inline brs_ext_result_t increase_destination_buffer(
|
20
|
-
VALUE
|
21
|
-
size_t
|
20
|
+
VALUE destination_value,
|
21
|
+
size_t destination_length,
|
22
|
+
size_t* remaining_destination_buffer_length_ptr,
|
23
|
+
size_t destination_buffer_length)
|
22
24
|
{
|
23
25
|
if (*remaining_destination_buffer_length_ptr == destination_buffer_length) {
|
24
26
|
// We want to write more data at once, than buffer has.
|
@@ -37,42 +39,63 @@ static inline brs_ext_result_t increase_destination_buffer(
|
|
37
39
|
return 0;
|
38
40
|
}
|
39
41
|
|
40
|
-
// -- utils --
|
41
|
-
|
42
|
-
#define GET_SOURCE_DATA(source_value) \
|
43
|
-
Check_Type(source_value, T_STRING); \
|
44
|
-
\
|
45
|
-
const char* source = RSTRING_PTR(source_value); \
|
46
|
-
size_t source_length = RSTRING_LEN(source_value);
|
47
|
-
|
48
42
|
// -- compress --
|
49
43
|
|
44
|
+
typedef struct
|
45
|
+
{
|
46
|
+
BrotliEncoderState* state_ptr;
|
47
|
+
const brs_ext_byte_t** remaining_source_ptr;
|
48
|
+
size_t* remaining_source_length_ptr;
|
49
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
50
|
+
size_t* remaining_destination_buffer_length_ptr;
|
51
|
+
BROTLI_BOOL result;
|
52
|
+
} compress_args_t;
|
53
|
+
|
54
|
+
static inline void* compress_wrapper(void* data)
|
55
|
+
{
|
56
|
+
compress_args_t* args = data;
|
57
|
+
|
58
|
+
args->result = BrotliEncoderCompressStream(
|
59
|
+
args->state_ptr,
|
60
|
+
BROTLI_OPERATION_FINISH,
|
61
|
+
args->remaining_source_length_ptr,
|
62
|
+
args->remaining_source_ptr,
|
63
|
+
args->remaining_destination_buffer_length_ptr,
|
64
|
+
&args->remaining_destination_buffer,
|
65
|
+
NULL);
|
66
|
+
|
67
|
+
return NULL;
|
68
|
+
}
|
69
|
+
|
50
70
|
static inline brs_ext_result_t compress(
|
51
71
|
BrotliEncoderState* state_ptr,
|
52
|
-
const char*
|
53
|
-
|
72
|
+
const char* source,
|
73
|
+
size_t source_length,
|
74
|
+
VALUE destination_value,
|
75
|
+
size_t destination_buffer_length,
|
76
|
+
bool gvl)
|
54
77
|
{
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
size_t
|
78
|
+
brs_ext_result_t ext_result;
|
79
|
+
const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
|
80
|
+
size_t remaining_source_length = source_length;
|
81
|
+
size_t destination_length = 0;
|
82
|
+
size_t remaining_destination_buffer_length = destination_buffer_length;
|
60
83
|
|
61
|
-
|
62
|
-
|
84
|
+
compress_args_t args = {
|
85
|
+
.state_ptr = state_ptr,
|
86
|
+
.remaining_source_ptr = &remaining_source,
|
87
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
63
88
|
|
64
89
|
while (true) {
|
65
|
-
brs_ext_byte_t* remaining_destination_buffer
|
66
|
-
|
90
|
+
brs_ext_byte_t* remaining_destination_buffer =
|
91
|
+
(brs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
|
92
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
67
93
|
|
68
|
-
|
69
|
-
|
70
|
-
BROTLI_OPERATION_FINISH,
|
71
|
-
&remaining_source_length, &remaining_source,
|
72
|
-
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
73
|
-
NULL);
|
94
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
95
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
74
96
|
|
75
|
-
|
97
|
+
BRS_EXT_GVL_WRAP(gvl, compress_wrapper, &args);
|
98
|
+
if (!args.result) {
|
76
99
|
return BRS_EXT_ERROR_UNEXPECTED;
|
77
100
|
}
|
78
101
|
|
@@ -80,8 +103,7 @@ static inline brs_ext_result_t compress(
|
|
80
103
|
|
81
104
|
if (BrotliEncoderHasMoreOutput(state_ptr) || !BrotliEncoderIsFinished(state_ptr)) {
|
82
105
|
ext_result = increase_destination_buffer(
|
83
|
-
destination_value, destination_length,
|
84
|
-
&remaining_destination_buffer_length, destination_buffer_length);
|
106
|
+
destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
|
85
107
|
|
86
108
|
if (ext_result != 0) {
|
87
109
|
return ext_result;
|
@@ -105,10 +127,11 @@ static inline brs_ext_result_t compress(
|
|
105
127
|
|
106
128
|
VALUE brs_ext_compress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VALUE options)
|
107
129
|
{
|
108
|
-
|
130
|
+
Check_Type(source_value, T_STRING);
|
109
131
|
Check_Type(options, T_HASH);
|
132
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
133
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
110
134
|
BRS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
111
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
112
135
|
|
113
136
|
BrotliEncoderState* state_ptr = BrotliEncoderCreateInstance(NULL, NULL, NULL);
|
114
137
|
if (state_ptr == NULL) {
|
@@ -133,10 +156,10 @@ VALUE brs_ext_compress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VA
|
|
133
156
|
brs_ext_raise_error(BRS_EXT_ERROR_ALLOCATE_FAILED);
|
134
157
|
}
|
135
158
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
159
|
+
const char* source = RSTRING_PTR(source_value);
|
160
|
+
size_t source_length = RSTRING_LEN(source_value);
|
161
|
+
|
162
|
+
ext_result = compress(state_ptr, source, source_length, destination_value, destination_buffer_length, gvl);
|
140
163
|
|
141
164
|
BrotliEncoderDestroyInstance(state_ptr);
|
142
165
|
|
@@ -149,44 +172,71 @@ VALUE brs_ext_compress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VA
|
|
149
172
|
|
150
173
|
// -- decompress --
|
151
174
|
|
175
|
+
typedef struct
|
176
|
+
{
|
177
|
+
BrotliDecoderState* state_ptr;
|
178
|
+
const brs_ext_byte_t** remaining_source_ptr;
|
179
|
+
size_t* remaining_source_length_ptr;
|
180
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
181
|
+
size_t* remaining_destination_buffer_length_ptr;
|
182
|
+
brs_ext_result_t result;
|
183
|
+
} decompress_args_t;
|
184
|
+
|
185
|
+
static inline void* decompress_wrapper(void* data)
|
186
|
+
{
|
187
|
+
decompress_args_t* args = data;
|
188
|
+
|
189
|
+
args->result = BrotliDecoderDecompressStream(
|
190
|
+
args->state_ptr,
|
191
|
+
args->remaining_source_length_ptr,
|
192
|
+
args->remaining_source_ptr,
|
193
|
+
args->remaining_destination_buffer_length_ptr,
|
194
|
+
&args->remaining_destination_buffer,
|
195
|
+
NULL);
|
196
|
+
|
197
|
+
return NULL;
|
198
|
+
}
|
199
|
+
|
152
200
|
static inline brs_ext_result_t decompress(
|
153
201
|
BrotliDecoderState* state_ptr,
|
154
|
-
const char*
|
155
|
-
|
202
|
+
const char* source,
|
203
|
+
size_t source_length,
|
204
|
+
VALUE destination_value,
|
205
|
+
size_t destination_buffer_length,
|
206
|
+
bool gvl)
|
156
207
|
{
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
size_t
|
208
|
+
brs_ext_result_t ext_result;
|
209
|
+
const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
|
210
|
+
size_t remaining_source_length = source_length;
|
211
|
+
size_t destination_length = 0;
|
212
|
+
size_t remaining_destination_buffer_length = destination_buffer_length;
|
162
213
|
|
163
|
-
|
164
|
-
|
214
|
+
decompress_args_t args = {
|
215
|
+
.state_ptr = state_ptr,
|
216
|
+
.remaining_source_ptr = &remaining_source,
|
217
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
165
218
|
|
166
219
|
while (true) {
|
167
|
-
brs_ext_byte_t* remaining_destination_buffer
|
168
|
-
|
220
|
+
brs_ext_byte_t* remaining_destination_buffer =
|
221
|
+
(brs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
|
222
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
169
223
|
|
170
|
-
|
171
|
-
|
172
|
-
&remaining_source_length, &remaining_source,
|
173
|
-
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
174
|
-
NULL);
|
224
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
225
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
175
226
|
|
227
|
+
BRS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
|
176
228
|
if (
|
177
|
-
result != BROTLI_DECODER_RESULT_SUCCESS &&
|
178
|
-
result !=
|
179
|
-
result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
229
|
+
args.result != BROTLI_DECODER_RESULT_SUCCESS && args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT &&
|
230
|
+
args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
180
231
|
BrotliDecoderErrorCode error_code = BrotliDecoderGetErrorCode(state_ptr);
|
181
232
|
return brs_ext_get_decompressor_error(error_code);
|
182
233
|
}
|
183
234
|
|
184
235
|
destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length;
|
185
236
|
|
186
|
-
if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
237
|
+
if (args.result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
187
238
|
ext_result = increase_destination_buffer(
|
188
|
-
destination_value, destination_length,
|
189
|
-
&remaining_destination_buffer_length, destination_buffer_length);
|
239
|
+
destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
|
190
240
|
|
191
241
|
if (ext_result != 0) {
|
192
242
|
return ext_result;
|
@@ -210,10 +260,11 @@ static inline brs_ext_result_t decompress(
|
|
210
260
|
|
211
261
|
VALUE brs_ext_decompress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VALUE options)
|
212
262
|
{
|
213
|
-
|
263
|
+
Check_Type(source_value, T_STRING);
|
214
264
|
Check_Type(options, T_HASH);
|
265
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
266
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
215
267
|
BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
216
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
217
268
|
|
218
269
|
BrotliDecoderState* state_ptr = BrotliDecoderCreateInstance(NULL, NULL, NULL);
|
219
270
|
if (state_ptr == NULL) {
|
@@ -238,10 +289,10 @@ VALUE brs_ext_decompress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value,
|
|
238
289
|
brs_ext_raise_error(BRS_EXT_ERROR_ALLOCATE_FAILED);
|
239
290
|
}
|
240
291
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
292
|
+
const char* source = RSTRING_PTR(source_value);
|
293
|
+
size_t source_length = RSTRING_LEN(source_value);
|
294
|
+
|
295
|
+
ext_result = decompress(state_ptr, source, source_length, destination_value, destination_buffer_length, gvl);
|
245
296
|
|
246
297
|
BrotliDecoderDestroyInstance(state_ptr);
|
247
298
|
|
@@ -252,6 +303,8 @@ VALUE brs_ext_decompress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value,
|
|
252
303
|
return destination_value;
|
253
304
|
}
|
254
305
|
|
306
|
+
// -- exports --
|
307
|
+
|
255
308
|
void brs_ext_string_exports(VALUE root_module)
|
256
309
|
{
|
257
310
|
rb_define_module_function(root_module, "_native_compress_string", RUBY_METHOD_FUNC(brs_ext_compress_string), 2);
|
data/ext/extconf.rb
CHANGED
@@ -3,17 +3,95 @@
|
|
3
3
|
|
4
4
|
require "mkmf"
|
5
5
|
|
6
|
-
|
6
|
+
have_func "rb_thread_call_without_gvl", "ruby/thread.h"
|
7
|
+
|
8
|
+
def require_header(name, constants: [], macroses: [], types: [])
|
7
9
|
abort "Can't find #{name} header" unless find_header name
|
8
10
|
|
11
|
+
constants.each do |constant|
|
12
|
+
abort "Can't find #{constant} constant in #{name} header" unless have_const constant, name
|
13
|
+
end
|
14
|
+
|
15
|
+
macroses.each do |macro|
|
16
|
+
abort "Can't find #{macro} macro in #{name} header" unless have_macro macro, name
|
17
|
+
end
|
18
|
+
|
9
19
|
types.each do |type|
|
10
20
|
abort "Can't find #{type} type in #{name} header" unless find_type type, nil, name
|
11
21
|
end
|
12
22
|
end
|
13
23
|
|
14
|
-
require_header
|
15
|
-
|
16
|
-
|
24
|
+
require_header(
|
25
|
+
"brotli/decode.h",
|
26
|
+
:constants => %w[
|
27
|
+
BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES
|
28
|
+
BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP
|
29
|
+
BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES
|
30
|
+
BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1
|
31
|
+
BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2
|
32
|
+
BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS
|
33
|
+
BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1
|
34
|
+
BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2
|
35
|
+
BROTLI_DECODER_ERROR_FORMAT_CL_SPACE
|
36
|
+
BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT
|
37
|
+
BROTLI_DECODER_ERROR_FORMAT_DICTIONARY
|
38
|
+
BROTLI_DECODER_ERROR_FORMAT_DISTANCE
|
39
|
+
BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE
|
40
|
+
BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE
|
41
|
+
BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE
|
42
|
+
BROTLI_DECODER_ERROR_FORMAT_PADDING_1
|
43
|
+
BROTLI_DECODER_ERROR_FORMAT_PADDING_2
|
44
|
+
BROTLI_DECODER_ERROR_FORMAT_RESERVED
|
45
|
+
BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET
|
46
|
+
BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME
|
47
|
+
BROTLI_DECODER_ERROR_FORMAT_TRANSFORM
|
48
|
+
BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS
|
49
|
+
BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION
|
50
|
+
BROTLI_DECODER_PARAM_LARGE_WINDOW
|
51
|
+
BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT
|
52
|
+
BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT
|
53
|
+
BROTLI_DECODER_RESULT_SUCCESS
|
54
|
+
],
|
55
|
+
:types => [
|
56
|
+
"BrotliDecoderErrorCode",
|
57
|
+
"BrotliDecoderResult",
|
58
|
+
"BrotliDecoderState *"
|
59
|
+
]
|
60
|
+
)
|
61
|
+
require_header(
|
62
|
+
"brotli/encode.h",
|
63
|
+
:constants => %w[
|
64
|
+
BROTLI_MAX_INPUT_BLOCK_BITS
|
65
|
+
BROTLI_MAX_QUALITY
|
66
|
+
BROTLI_MAX_WINDOW_BITS
|
67
|
+
BROTLI_MIN_INPUT_BLOCK_BITS
|
68
|
+
BROTLI_MIN_QUALITY
|
69
|
+
BROTLI_MIN_WINDOW_BITS
|
70
|
+
BROTLI_MODE_FONT
|
71
|
+
BROTLI_MODE_GENERIC
|
72
|
+
BROTLI_MODE_TEXT
|
73
|
+
BROTLI_OPERATION_FINISH
|
74
|
+
BROTLI_OPERATION_FLUSH
|
75
|
+
BROTLI_OPERATION_PROCESS
|
76
|
+
BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING
|
77
|
+
BROTLI_PARAM_LARGE_WINDOW
|
78
|
+
BROTLI_PARAM_LGBLOCK
|
79
|
+
BROTLI_PARAM_LGWIN
|
80
|
+
BROTLI_PARAM_NDIRECT
|
81
|
+
BROTLI_PARAM_NPOSTFIX
|
82
|
+
BROTLI_PARAM_MODE
|
83
|
+
BROTLI_PARAM_QUALITY
|
84
|
+
BROTLI_PARAM_SIZE_HINT
|
85
|
+
],
|
86
|
+
:types => [
|
87
|
+
"BrotliEncoderMode",
|
88
|
+
"BrotliEncoderState *"
|
89
|
+
]
|
90
|
+
)
|
91
|
+
require_header(
|
92
|
+
"brotli/types.h",
|
93
|
+
:macroses => %w[BROTLI_BOOL]
|
94
|
+
)
|
17
95
|
|
18
96
|
def require_library(name, functions)
|
19
97
|
functions.each do |function|
|
@@ -24,12 +102,13 @@ end
|
|
24
102
|
require_library(
|
25
103
|
"brotlienc",
|
26
104
|
%w[
|
27
|
-
BrotliEncoderCreateInstance
|
28
|
-
BrotliEncoderSetParameter
|
29
105
|
BrotliEncoderCompressStream
|
106
|
+
BrotliEncoderCreateInstance
|
107
|
+
BrotliEncoderDestroyInstance
|
30
108
|
BrotliEncoderHasMoreOutput
|
31
109
|
BrotliEncoderIsFinished
|
32
|
-
|
110
|
+
BrotliEncoderSetParameter
|
111
|
+
BrotliEncoderVersion
|
33
112
|
]
|
34
113
|
)
|
35
114
|
|
@@ -37,10 +116,11 @@ require_library(
|
|
37
116
|
"brotlidec",
|
38
117
|
%w[
|
39
118
|
BrotliDecoderCreateInstance
|
40
|
-
BrotliDecoderSetParameter
|
41
119
|
BrotliDecoderDecompressStream
|
42
|
-
BrotliDecoderGetErrorCode
|
43
120
|
BrotliDecoderDestroyInstance
|
121
|
+
BrotliDecoderGetErrorCode
|
122
|
+
BrotliDecoderSetParameter
|
123
|
+
BrotliDecoderVersion
|
44
124
|
]
|
45
125
|
)
|
46
126
|
|
@@ -68,7 +148,7 @@ $libs = $libs.split(%r{\s})
|
|
68
148
|
.uniq
|
69
149
|
.join " "
|
70
150
|
|
71
|
-
if ENV["CI"]
|
151
|
+
if ENV["CI"]
|
72
152
|
$CFLAGS << " --coverage"
|
73
153
|
$LDFLAGS << " --coverage"
|
74
154
|
end
|
data/lib/brs/file.rb
CHANGED
@@ -19,7 +19,7 @@ module BRS
|
|
19
19
|
|
20
20
|
options[:size_hint] = ::File.size source
|
21
21
|
|
22
|
-
open_files
|
22
|
+
open_files source, destination do |source_io, destination_io|
|
23
23
|
BRS._native_compress_io source_io, destination_io, options
|
24
24
|
end
|
25
25
|
|
@@ -32,7 +32,7 @@ module BRS
|
|
32
32
|
|
33
33
|
options = Option.get_decompressor_options options, BUFFER_LENGTH_NAMES
|
34
34
|
|
35
|
-
open_files
|
35
|
+
open_files source, destination do |source_io, destination_io|
|
36
36
|
BRS._native_decompress_io source_io, destination_io, options
|
37
37
|
end
|
38
38
|
|