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
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
|
}
|