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
data/ext/brs_ext/io.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Ruby bindings for brotli library.
|
2
2
|
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
3
|
|
4
|
-
#include "
|
4
|
+
#include "brs_ext/io.h"
|
5
5
|
|
6
6
|
#include <brotli/decode.h>
|
7
7
|
#include <brotli/encode.h>
|
@@ -12,19 +12,21 @@
|
|
12
12
|
|
13
13
|
#include "brs_ext/buffer.h"
|
14
14
|
#include "brs_ext/error.h"
|
15
|
-
#include "brs_ext/
|
15
|
+
#include "brs_ext/gvl.h"
|
16
16
|
#include "brs_ext/macro.h"
|
17
17
|
#include "brs_ext/option.h"
|
18
|
-
#include "ruby.h"
|
18
|
+
#include "ruby/io.h"
|
19
19
|
|
20
20
|
// Additional possible results:
|
21
|
-
enum
|
21
|
+
enum
|
22
|
+
{
|
22
23
|
BRS_EXT_FILE_READ_FINISHED = 128
|
23
24
|
};
|
24
25
|
|
25
26
|
// -- file --
|
26
27
|
|
27
|
-
static inline brs_ext_result_t
|
28
|
+
static inline brs_ext_result_t
|
29
|
+
read_file(FILE* source_file, brs_ext_byte_t* source_buffer, size_t* source_length_ptr, size_t source_buffer_length)
|
28
30
|
{
|
29
31
|
size_t read_length = fread(source_buffer, 1, source_buffer_length, source_file);
|
30
32
|
if (read_length == 0 && feof(source_file)) {
|
@@ -40,7 +42,8 @@ static inline brs_ext_result_t read_file(FILE* source_file, brs_ext_byte_t* sour
|
|
40
42
|
return 0;
|
41
43
|
}
|
42
44
|
|
43
|
-
static inline brs_ext_result_t
|
45
|
+
static inline brs_ext_result_t
|
46
|
+
write_file(FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_length)
|
44
47
|
{
|
45
48
|
size_t written_length = fwrite(destination_buffer, 1, destination_length, destination_file);
|
46
49
|
if (written_length != destination_length) {
|
@@ -53,8 +56,10 @@ static inline brs_ext_result_t write_file(FILE* destination_file, brs_ext_byte_t
|
|
53
56
|
// -- buffer --
|
54
57
|
|
55
58
|
static inline brs_ext_result_t create_buffers(
|
56
|
-
brs_ext_byte_t** source_buffer_ptr,
|
57
|
-
|
59
|
+
brs_ext_byte_t** source_buffer_ptr,
|
60
|
+
size_t source_buffer_length,
|
61
|
+
brs_ext_byte_t** destination_buffer_ptr,
|
62
|
+
size_t destination_buffer_length)
|
58
63
|
{
|
59
64
|
brs_ext_byte_t* source_buffer = malloc(source_buffer_length);
|
60
65
|
if (source_buffer == NULL) {
|
@@ -81,8 +86,10 @@ static inline brs_ext_result_t create_buffers(
|
|
81
86
|
|
82
87
|
static inline brs_ext_result_t read_more_source(
|
83
88
|
FILE* source_file,
|
84
|
-
const brs_ext_byte_t** source_ptr,
|
85
|
-
|
89
|
+
const brs_ext_byte_t** source_ptr,
|
90
|
+
size_t* source_length_ptr,
|
91
|
+
brs_ext_byte_t* source_buffer,
|
92
|
+
size_t source_buffer_length)
|
86
93
|
{
|
87
94
|
const brs_ext_byte_t* source = *source_ptr;
|
88
95
|
size_t source_length = *source_length_ptr;
|
@@ -105,7 +112,9 @@ static inline brs_ext_result_t read_more_source(
|
|
105
112
|
brs_ext_byte_t* remaining_source_buffer = source_buffer + source_length;
|
106
113
|
size_t new_source_length;
|
107
114
|
|
108
|
-
brs_ext_result_t ext_result =
|
115
|
+
brs_ext_result_t ext_result =
|
116
|
+
read_file(source_file, remaining_source_buffer, &new_source_length, remaining_source_buffer_length);
|
117
|
+
|
109
118
|
if (ext_result != 0) {
|
110
119
|
return ext_result;
|
111
120
|
}
|
@@ -115,42 +124,37 @@ static inline brs_ext_result_t read_more_source(
|
|
115
124
|
return 0;
|
116
125
|
}
|
117
126
|
|
118
|
-
#define BUFFERED_READ_SOURCE(function, ...)
|
119
|
-
do {
|
120
|
-
bool is_function_called = false;
|
121
|
-
|
122
|
-
while (true) {
|
123
|
-
ext_result = read_more_source(
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
return ext_result;
|
137
|
-
}
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
ext_result = function(__VA_ARGS__); \
|
150
|
-
if (ext_result != 0) { \
|
151
|
-
return ext_result; \
|
152
|
-
} \
|
153
|
-
} \
|
127
|
+
#define BUFFERED_READ_SOURCE(function, ...) \
|
128
|
+
do { \
|
129
|
+
bool is_function_called = false; \
|
130
|
+
\
|
131
|
+
while (true) { \
|
132
|
+
ext_result = read_more_source(source_file, &source, &source_length, source_buffer, source_buffer_length); \
|
133
|
+
if (ext_result == BRS_EXT_FILE_READ_FINISHED) { \
|
134
|
+
if (source_length != 0) { \
|
135
|
+
/* Brotli won't provide any remainder by design. */ \
|
136
|
+
return BRS_EXT_ERROR_READ_IO; \
|
137
|
+
} \
|
138
|
+
break; \
|
139
|
+
} else if (ext_result != 0) { \
|
140
|
+
return ext_result; \
|
141
|
+
} \
|
142
|
+
\
|
143
|
+
ext_result = function(__VA_ARGS__); \
|
144
|
+
if (ext_result != 0) { \
|
145
|
+
return ext_result; \
|
146
|
+
} \
|
147
|
+
\
|
148
|
+
is_function_called = true; \
|
149
|
+
} \
|
150
|
+
\
|
151
|
+
if (!is_function_called) { \
|
152
|
+
/* Function should be called at least once. */ \
|
153
|
+
ext_result = function(__VA_ARGS__); \
|
154
|
+
if (ext_result != 0) { \
|
155
|
+
return ext_result; \
|
156
|
+
} \
|
157
|
+
} \
|
154
158
|
} while (false);
|
155
159
|
|
156
160
|
// Algorithm has written data into destination buffer.
|
@@ -159,7 +163,9 @@ static inline brs_ext_result_t read_more_source(
|
|
159
163
|
|
160
164
|
static inline brs_ext_result_t flush_destination_buffer(
|
161
165
|
FILE* destination_file,
|
162
|
-
brs_ext_byte_t* destination_buffer,
|
166
|
+
brs_ext_byte_t* destination_buffer,
|
167
|
+
size_t* destination_length_ptr,
|
168
|
+
size_t destination_buffer_length)
|
163
169
|
{
|
164
170
|
if (*destination_length_ptr == 0) {
|
165
171
|
// We want to write more data at once, than buffer has.
|
@@ -176,7 +182,8 @@ static inline brs_ext_result_t flush_destination_buffer(
|
|
176
182
|
return 0;
|
177
183
|
}
|
178
184
|
|
179
|
-
static inline brs_ext_result_t
|
185
|
+
static inline brs_ext_result_t
|
186
|
+
write_remaining_destination(FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_length)
|
180
187
|
{
|
181
188
|
if (destination_length == 0) {
|
182
189
|
return 0;
|
@@ -198,29 +205,57 @@ static inline brs_ext_result_t write_remaining_destination(FILE* destination_fil
|
|
198
205
|
brs_ext_raise_error(BRS_EXT_ERROR_ACCESS_IO); \
|
199
206
|
}
|
200
207
|
|
201
|
-
// -- compress --
|
208
|
+
// -- buffered compress --
|
209
|
+
|
210
|
+
typedef struct
|
211
|
+
{
|
212
|
+
BrotliEncoderState* state_ptr;
|
213
|
+
const brs_ext_byte_t** source_ptr;
|
214
|
+
size_t* source_length_ptr;
|
215
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
216
|
+
size_t* remaining_destination_buffer_length_ptr;
|
217
|
+
BROTLI_BOOL result;
|
218
|
+
} compress_args_t;
|
219
|
+
|
220
|
+
static inline void* compress_wrapper(void* data)
|
221
|
+
{
|
222
|
+
compress_args_t* args = data;
|
223
|
+
|
224
|
+
args->result = BrotliEncoderCompressStream(
|
225
|
+
args->state_ptr,
|
226
|
+
BROTLI_OPERATION_PROCESS,
|
227
|
+
args->source_length_ptr,
|
228
|
+
args->source_ptr,
|
229
|
+
args->remaining_destination_buffer_length_ptr,
|
230
|
+
&args->remaining_destination_buffer,
|
231
|
+
NULL);
|
232
|
+
|
233
|
+
return NULL;
|
234
|
+
}
|
202
235
|
|
203
236
|
static inline brs_ext_result_t buffered_compress(
|
204
237
|
BrotliEncoderState* state_ptr,
|
205
|
-
const brs_ext_byte_t** source_ptr,
|
206
|
-
|
238
|
+
const brs_ext_byte_t** source_ptr,
|
239
|
+
size_t* source_length_ptr,
|
240
|
+
FILE* destination_file,
|
241
|
+
brs_ext_byte_t* destination_buffer,
|
242
|
+
size_t* destination_length_ptr,
|
243
|
+
size_t destination_buffer_length,
|
244
|
+
bool gvl)
|
207
245
|
{
|
208
|
-
BROTLI_BOOL result;
|
209
246
|
brs_ext_result_t ext_result;
|
247
|
+
compress_args_t args = {.state_ptr = state_ptr, .source_ptr = source_ptr, .source_length_ptr = source_length_ptr};
|
210
248
|
|
211
249
|
while (true) {
|
212
250
|
brs_ext_byte_t* remaining_destination_buffer = destination_buffer + *destination_length_ptr;
|
213
251
|
size_t remaining_destination_buffer_length = destination_buffer_length - *destination_length_ptr;
|
214
252
|
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
215
253
|
|
216
|
-
|
217
|
-
|
218
|
-
BROTLI_OPERATION_PROCESS,
|
219
|
-
source_length_ptr, source_ptr,
|
220
|
-
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
221
|
-
NULL);
|
254
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
255
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
222
256
|
|
223
|
-
|
257
|
+
BRS_EXT_GVL_WRAP(gvl, compress_wrapper, &args);
|
258
|
+
if (!args.result) {
|
224
259
|
return BRS_EXT_ERROR_UNEXPECTED;
|
225
260
|
}
|
226
261
|
|
@@ -228,8 +263,7 @@ static inline brs_ext_result_t buffered_compress(
|
|
228
263
|
|
229
264
|
if (BrotliEncoderHasMoreOutput(state_ptr)) {
|
230
265
|
ext_result = flush_destination_buffer(
|
231
|
-
destination_file,
|
232
|
-
destination_buffer, destination_length_ptr, destination_buffer_length);
|
266
|
+
destination_file, destination_buffer, destination_length_ptr, destination_buffer_length);
|
233
267
|
|
234
268
|
if (ext_result != 0) {
|
235
269
|
return ext_result;
|
@@ -244,29 +278,57 @@ static inline brs_ext_result_t buffered_compress(
|
|
244
278
|
return 0;
|
245
279
|
}
|
246
280
|
|
281
|
+
// -- buffered compressor finish --
|
282
|
+
|
283
|
+
typedef struct
|
284
|
+
{
|
285
|
+
BrotliEncoderState* state_ptr;
|
286
|
+
const brs_ext_byte_t** source_ptr;
|
287
|
+
size_t* source_length_ptr;
|
288
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
289
|
+
size_t* remaining_destination_buffer_length_ptr;
|
290
|
+
BROTLI_BOOL result;
|
291
|
+
} compressor_finish_args_t;
|
292
|
+
|
293
|
+
static inline void* compressor_finish_wrapper(void* data)
|
294
|
+
{
|
295
|
+
compressor_finish_args_t* args = data;
|
296
|
+
|
297
|
+
args->result = BrotliEncoderCompressStream(
|
298
|
+
args->state_ptr,
|
299
|
+
BROTLI_OPERATION_FINISH,
|
300
|
+
args->source_length_ptr,
|
301
|
+
args->source_ptr,
|
302
|
+
args->remaining_destination_buffer_length_ptr,
|
303
|
+
&args->remaining_destination_buffer,
|
304
|
+
NULL);
|
305
|
+
|
306
|
+
return NULL;
|
307
|
+
}
|
308
|
+
|
247
309
|
static inline brs_ext_result_t buffered_compressor_finish(
|
248
310
|
BrotliEncoderState* state_ptr,
|
249
|
-
FILE*
|
311
|
+
FILE* destination_file,
|
312
|
+
brs_ext_byte_t* destination_buffer,
|
313
|
+
size_t* destination_length_ptr,
|
314
|
+
size_t destination_buffer_length,
|
315
|
+
bool gvl)
|
250
316
|
{
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
size_t source_length = 0;
|
317
|
+
brs_ext_result_t ext_result;
|
318
|
+
const brs_ext_byte_t* source = NULL;
|
319
|
+
size_t source_length = 0;
|
320
|
+
compressor_finish_args_t args = {.state_ptr = state_ptr, .source_ptr = &source, .source_length_ptr = &source_length};
|
256
321
|
|
257
322
|
while (true) {
|
258
323
|
brs_ext_byte_t* remaining_destination_buffer = destination_buffer + *destination_length_ptr;
|
259
324
|
size_t remaining_destination_buffer_length = destination_buffer_length - *destination_length_ptr;
|
260
325
|
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
261
326
|
|
262
|
-
|
263
|
-
|
264
|
-
BROTLI_OPERATION_FINISH,
|
265
|
-
&source_length, &source,
|
266
|
-
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
267
|
-
NULL);
|
327
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
328
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
268
329
|
|
269
|
-
|
330
|
+
BRS_EXT_GVL_WRAP(gvl, compressor_finish_wrapper, &args);
|
331
|
+
if (!args.result) {
|
270
332
|
return BRS_EXT_ERROR_UNEXPECTED;
|
271
333
|
}
|
272
334
|
|
@@ -274,8 +336,7 @@ static inline brs_ext_result_t buffered_compressor_finish(
|
|
274
336
|
|
275
337
|
if (BrotliEncoderHasMoreOutput(state_ptr) || !BrotliEncoderIsFinished(state_ptr)) {
|
276
338
|
ext_result = flush_destination_buffer(
|
277
|
-
destination_file,
|
278
|
-
destination_buffer, destination_length_ptr, destination_buffer_length);
|
339
|
+
destination_file, destination_buffer, destination_length_ptr, destination_buffer_length);
|
279
340
|
|
280
341
|
if (ext_result != 0) {
|
281
342
|
return ext_result;
|
@@ -290,13 +351,19 @@ static inline brs_ext_result_t buffered_compressor_finish(
|
|
290
351
|
return 0;
|
291
352
|
}
|
292
353
|
|
354
|
+
// -- compress --
|
355
|
+
|
293
356
|
static inline brs_ext_result_t compress(
|
294
357
|
BrotliEncoderState* state_ptr,
|
295
|
-
FILE*
|
296
|
-
|
358
|
+
FILE* source_file,
|
359
|
+
brs_ext_byte_t* source_buffer,
|
360
|
+
size_t source_buffer_length,
|
361
|
+
FILE* destination_file,
|
362
|
+
brs_ext_byte_t* destination_buffer,
|
363
|
+
size_t destination_buffer_length,
|
364
|
+
bool gvl)
|
297
365
|
{
|
298
|
-
brs_ext_result_t
|
299
|
-
|
366
|
+
brs_ext_result_t ext_result;
|
300
367
|
const brs_ext_byte_t* source = source_buffer;
|
301
368
|
size_t source_length = 0;
|
302
369
|
size_t destination_length = 0;
|
@@ -304,12 +371,16 @@ static inline brs_ext_result_t compress(
|
|
304
371
|
BUFFERED_READ_SOURCE(
|
305
372
|
buffered_compress,
|
306
373
|
state_ptr,
|
307
|
-
&source,
|
308
|
-
|
374
|
+
&source,
|
375
|
+
&source_length,
|
376
|
+
destination_file,
|
377
|
+
destination_buffer,
|
378
|
+
&destination_length,
|
379
|
+
destination_buffer_length,
|
380
|
+
gvl);
|
309
381
|
|
310
382
|
ext_result = buffered_compressor_finish(
|
311
|
-
state_ptr,
|
312
|
-
destination_file, destination_buffer, &destination_length, destination_buffer_length);
|
383
|
+
state_ptr, destination_file, destination_buffer, &destination_length, destination_buffer_length, gvl);
|
313
384
|
|
314
385
|
if (ext_result != 0) {
|
315
386
|
return ext_result;
|
@@ -323,9 +394,10 @@ VALUE brs_ext_compress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE destin
|
|
323
394
|
GET_FILE(source);
|
324
395
|
GET_FILE(destination);
|
325
396
|
Check_Type(options, T_HASH);
|
397
|
+
BRS_EXT_GET_SIZE_OPTION(options, source_buffer_length);
|
398
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
399
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
326
400
|
BRS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
327
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, source_buffer_length);
|
328
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
329
401
|
|
330
402
|
BrotliEncoderState* state_ptr = BrotliEncoderCreateInstance(NULL, NULL, NULL);
|
331
403
|
if (state_ptr == NULL) {
|
@@ -348,10 +420,7 @@ VALUE brs_ext_compress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE destin
|
|
348
420
|
brs_ext_byte_t* source_buffer;
|
349
421
|
brs_ext_byte_t* destination_buffer;
|
350
422
|
|
351
|
-
ext_result = create_buffers(
|
352
|
-
&source_buffer, source_buffer_length,
|
353
|
-
&destination_buffer, destination_buffer_length);
|
354
|
-
|
423
|
+
ext_result = create_buffers(&source_buffer, source_buffer_length, &destination_buffer, destination_buffer_length);
|
355
424
|
if (ext_result != 0) {
|
356
425
|
BrotliEncoderDestroyInstance(state_ptr);
|
357
426
|
brs_ext_raise_error(ext_result);
|
@@ -359,8 +428,13 @@ VALUE brs_ext_compress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE destin
|
|
359
428
|
|
360
429
|
ext_result = compress(
|
361
430
|
state_ptr,
|
362
|
-
source_file,
|
363
|
-
|
431
|
+
source_file,
|
432
|
+
source_buffer,
|
433
|
+
source_buffer_length,
|
434
|
+
destination_file,
|
435
|
+
destination_buffer,
|
436
|
+
destination_buffer_length,
|
437
|
+
gvl);
|
364
438
|
|
365
439
|
free(source_buffer);
|
366
440
|
free(destination_buffer);
|
@@ -376,41 +450,68 @@ VALUE brs_ext_compress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE destin
|
|
376
450
|
return Qnil;
|
377
451
|
}
|
378
452
|
|
379
|
-
// -- decompress --
|
453
|
+
// -- buffered decompress --
|
454
|
+
|
455
|
+
typedef struct
|
456
|
+
{
|
457
|
+
BrotliDecoderState* state_ptr;
|
458
|
+
const brs_ext_byte_t** source_ptr;
|
459
|
+
size_t* source_length_ptr;
|
460
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
461
|
+
size_t* remaining_destination_buffer_length_ptr;
|
462
|
+
BrotliDecoderResult result;
|
463
|
+
} decompress_args_t;
|
464
|
+
|
465
|
+
static inline void* decompress_wrapper(void* data)
|
466
|
+
{
|
467
|
+
decompress_args_t* args = data;
|
468
|
+
|
469
|
+
args->result = BrotliDecoderDecompressStream(
|
470
|
+
args->state_ptr,
|
471
|
+
args->source_length_ptr,
|
472
|
+
args->source_ptr,
|
473
|
+
args->remaining_destination_buffer_length_ptr,
|
474
|
+
&args->remaining_destination_buffer,
|
475
|
+
NULL);
|
476
|
+
|
477
|
+
return NULL;
|
478
|
+
}
|
380
479
|
|
381
480
|
static inline brs_ext_result_t buffered_decompress(
|
382
481
|
BrotliDecoderState* state_ptr,
|
383
|
-
const brs_ext_byte_t** source_ptr,
|
384
|
-
|
482
|
+
const brs_ext_byte_t** source_ptr,
|
483
|
+
size_t* source_length_ptr,
|
484
|
+
FILE* destination_file,
|
485
|
+
brs_ext_byte_t* destination_buffer,
|
486
|
+
size_t* destination_length_ptr,
|
487
|
+
size_t destination_buffer_length,
|
488
|
+
bool gvl)
|
385
489
|
{
|
386
|
-
|
387
|
-
|
490
|
+
brs_ext_result_t ext_result;
|
491
|
+
decompress_args_t args = {.state_ptr = state_ptr, .source_ptr = source_ptr, .source_length_ptr = source_length_ptr};
|
388
492
|
|
389
493
|
while (true) {
|
390
494
|
brs_ext_byte_t* remaining_destination_buffer = destination_buffer + *destination_length_ptr;
|
391
495
|
size_t remaining_destination_buffer_length = destination_buffer_length - *destination_length_ptr;
|
392
496
|
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
393
497
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
NULL);
|
498
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
499
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
500
|
+
|
501
|
+
BRS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
|
399
502
|
|
400
503
|
if (
|
401
|
-
result != BROTLI_DECODER_RESULT_SUCCESS &&
|
402
|
-
result !=
|
403
|
-
result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
504
|
+
args.result != BROTLI_DECODER_RESULT_SUCCESS && args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT &&
|
505
|
+
args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
404
506
|
BrotliDecoderErrorCode error_code = BrotliDecoderGetErrorCode(state_ptr);
|
405
507
|
return brs_ext_get_decompressor_error(error_code);
|
406
508
|
}
|
407
509
|
|
408
510
|
*destination_length_ptr += prev_remaining_destination_buffer_length - remaining_destination_buffer_length;
|
409
511
|
|
410
|
-
if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
512
|
+
if (args.result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
411
513
|
ext_result = flush_destination_buffer(
|
412
|
-
destination_file,
|
413
|
-
destination_buffer, destination_length_ptr, destination_buffer_length);
|
514
|
+
destination_file, destination_buffer, destination_length_ptr, destination_buffer_length);
|
414
515
|
|
415
516
|
if (ext_result != 0) {
|
416
517
|
return ext_result;
|
@@ -425,13 +526,19 @@ static inline brs_ext_result_t buffered_decompress(
|
|
425
526
|
return 0;
|
426
527
|
}
|
427
528
|
|
529
|
+
// -- decompress --
|
530
|
+
|
428
531
|
static inline brs_ext_result_t decompress(
|
429
532
|
BrotliDecoderState* state_ptr,
|
430
|
-
FILE*
|
431
|
-
|
533
|
+
FILE* source_file,
|
534
|
+
brs_ext_byte_t* source_buffer,
|
535
|
+
size_t source_buffer_length,
|
536
|
+
FILE* destination_file,
|
537
|
+
brs_ext_byte_t* destination_buffer,
|
538
|
+
size_t destination_buffer_length,
|
539
|
+
bool gvl)
|
432
540
|
{
|
433
|
-
brs_ext_result_t
|
434
|
-
|
541
|
+
brs_ext_result_t ext_result;
|
435
542
|
const brs_ext_byte_t* source = source_buffer;
|
436
543
|
size_t source_length = 0;
|
437
544
|
size_t destination_length = 0;
|
@@ -439,8 +546,13 @@ static inline brs_ext_result_t decompress(
|
|
439
546
|
BUFFERED_READ_SOURCE(
|
440
547
|
buffered_decompress,
|
441
548
|
state_ptr,
|
442
|
-
&source,
|
443
|
-
|
549
|
+
&source,
|
550
|
+
&source_length,
|
551
|
+
destination_file,
|
552
|
+
destination_buffer,
|
553
|
+
&destination_length,
|
554
|
+
destination_buffer_length,
|
555
|
+
gvl);
|
444
556
|
|
445
557
|
return write_remaining_destination(destination_file, destination_buffer, destination_length);
|
446
558
|
}
|
@@ -450,9 +562,10 @@ VALUE brs_ext_decompress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE dest
|
|
450
562
|
GET_FILE(source);
|
451
563
|
GET_FILE(destination);
|
452
564
|
Check_Type(options, T_HASH);
|
565
|
+
BRS_EXT_GET_SIZE_OPTION(options, source_buffer_length);
|
566
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
567
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
453
568
|
BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
454
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, source_buffer_length);
|
455
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
456
569
|
|
457
570
|
BrotliDecoderState* state_ptr = BrotliDecoderCreateInstance(NULL, NULL, NULL);
|
458
571
|
if (state_ptr == NULL) {
|
@@ -475,10 +588,7 @@ VALUE brs_ext_decompress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE dest
|
|
475
588
|
brs_ext_byte_t* source_buffer;
|
476
589
|
brs_ext_byte_t* destination_buffer;
|
477
590
|
|
478
|
-
ext_result = create_buffers(
|
479
|
-
&source_buffer, source_buffer_length,
|
480
|
-
&destination_buffer, destination_buffer_length);
|
481
|
-
|
591
|
+
ext_result = create_buffers(&source_buffer, source_buffer_length, &destination_buffer, destination_buffer_length);
|
482
592
|
if (ext_result != 0) {
|
483
593
|
BrotliDecoderDestroyInstance(state_ptr);
|
484
594
|
brs_ext_raise_error(ext_result);
|
@@ -486,8 +596,13 @@ VALUE brs_ext_decompress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE dest
|
|
486
596
|
|
487
597
|
ext_result = decompress(
|
488
598
|
state_ptr,
|
489
|
-
source_file,
|
490
|
-
|
599
|
+
source_file,
|
600
|
+
source_buffer,
|
601
|
+
source_buffer_length,
|
602
|
+
destination_file,
|
603
|
+
destination_buffer,
|
604
|
+
destination_buffer_length,
|
605
|
+
gvl);
|
491
606
|
|
492
607
|
free(source_buffer);
|
493
608
|
free(destination_buffer);
|
@@ -503,6 +618,8 @@ VALUE brs_ext_decompress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE dest
|
|
503
618
|
return Qnil;
|
504
619
|
}
|
505
620
|
|
621
|
+
// -- exports --
|
622
|
+
|
506
623
|
void brs_ext_io_exports(VALUE root_module)
|
507
624
|
{
|
508
625
|
rb_define_module_function(root_module, "_native_compress_io", RUBY_METHOD_FUNC(brs_ext_compress_io), 3);
|
data/ext/brs_ext/main.c
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
#include "brs_ext/stream/compressor.h"
|
8
8
|
#include "brs_ext/stream/decompressor.h"
|
9
9
|
#include "brs_ext/string.h"
|
10
|
-
#include "ruby.h"
|
11
10
|
|
12
11
|
void Init_brs_ext()
|
13
12
|
{
|
@@ -19,4 +18,8 @@ void Init_brs_ext()
|
|
19
18
|
brs_ext_compressor_exports(root_module);
|
20
19
|
brs_ext_decompressor_exports(root_module);
|
21
20
|
brs_ext_string_exports(root_module);
|
21
|
+
|
22
|
+
VALUE version_arguments[] = {INT2FIX(16)};
|
23
|
+
VALUE version = rb_block_call(UINT2NUM(BrotliEncoderVersion()), rb_intern("to_s"), 1, version_arguments, 0, 0);
|
24
|
+
rb_define_const(root_module, "LIBRARY_VERSION", rb_obj_freeze(version));
|
22
25
|
}
|