ruby-brs 1.1.4 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|