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.
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 "ruby/io.h"
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/io.h"
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 read_file(FILE* source_file, brs_ext_byte_t* source_buffer, size_t* source_length_ptr, size_t source_buffer_length)
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 write_file(FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_length)
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, size_t source_buffer_length,
57
- brs_ext_byte_t** destination_buffer_ptr, size_t destination_buffer_length)
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, size_t* source_length_ptr,
85
- brs_ext_byte_t* source_buffer, size_t source_buffer_length)
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 = read_file(source_file, remaining_source_buffer, &new_source_length, remaining_source_buffer_length);
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
- source_file, \
125
- &source, &source_length, \
126
- source_buffer, source_buffer_length); \
127
- \
128
- if (ext_result == BRS_EXT_FILE_READ_FINISHED) { \
129
- if (source_length != 0) { \
130
- /* Brotli won't provide any remainder by design. */ \
131
- return BRS_EXT_ERROR_READ_IO; \
132
- } \
133
- break; \
134
- } \
135
- else if (ext_result != 0) { \
136
- return ext_result; \
137
- } \
138
- \
139
- ext_result = function(__VA_ARGS__); \
140
- if (ext_result != 0) { \
141
- return ext_result; \
142
- } \
143
- \
144
- is_function_called = true; \
145
- } \
146
- \
147
- if (!is_function_called) { \
148
- /* Function should be called at least once. */ \
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, size_t* destination_length_ptr, size_t destination_buffer_length)
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 write_remaining_destination(FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_length)
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, size_t* source_length_ptr,
206
- FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
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
- result = BrotliEncoderCompressStream(
217
- state_ptr,
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
- if (!result) {
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* destination_file, brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
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
- BROTLI_BOOL result;
252
- brs_ext_result_t ext_result;
253
-
254
- const brs_ext_byte_t* source = NULL;
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
- result = BrotliEncoderCompressStream(
263
- state_ptr,
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
- if (!result) {
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* source_file, brs_ext_byte_t* source_buffer, size_t source_buffer_length,
296
- FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_buffer_length)
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 ext_result;
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, &source_length,
308
- destination_file, destination_buffer, &destination_length, destination_buffer_length);
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, source_buffer, source_buffer_length,
363
- destination_file, destination_buffer, destination_buffer_length);
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, size_t* source_length_ptr,
384
- FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
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
- BrotliDecoderResult result;
387
- brs_ext_result_t ext_result;
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
- result = BrotliDecoderDecompressStream(
395
- state_ptr,
396
- source_length_ptr, source_ptr,
397
- &remaining_destination_buffer_length, &remaining_destination_buffer,
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 != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT &&
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* source_file, brs_ext_byte_t* source_buffer, size_t source_buffer_length,
431
- FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_buffer_length)
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 ext_result;
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, &source_length,
443
- destination_file, destination_buffer, &destination_length, destination_buffer_length);
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, source_buffer, source_buffer_length,
490
- destination_file, destination_buffer, destination_buffer_length);
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
  }