ruby-brs 1.1.1 → 1.2.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 +87 -85
- data/ext/brs_ext/buffer.c +21 -7
- data/ext/brs_ext/buffer.h +7 -7
- data/ext/brs_ext/common.h +3 -0
- data/ext/brs_ext/error.c +0 -1
- data/ext/brs_ext/error.h +2 -1
- data/ext/brs_ext/gvl.h +24 -0
- data/ext/brs_ext/io.c +273 -157
- data/ext/brs_ext/main.c +0 -1
- data/ext/brs_ext/option.c +37 -30
- data/ext/brs_ext/option.h +39 -32
- data/ext/brs_ext/stream/compressor.c +124 -61
- data/ext/brs_ext/stream/compressor.h +7 -4
- data/ext/brs_ext/stream/decompressor.c +60 -31
- data/ext/brs_ext/stream/decompressor.h +7 -4
- data/ext/brs_ext/string.c +118 -66
- data/ext/extconf.rb +9 -0
- data/lib/brs/file.rb +4 -0
- data/lib/brs/option.rb +6 -0
- data/lib/brs/stream/abstract.rb +9 -12
- data/lib/brs/stream/raw/abstract.rb +6 -2
- data/lib/brs/stream/raw/compressor.rb +3 -7
- data/lib/brs/stream/raw/decompressor.rb +1 -5
- data/lib/brs/stream/reader.rb +71 -52
- data/lib/brs/stream/writer.rb +10 -5
- data/lib/brs/stream/writer_helpers.rb +6 -5
- data/lib/brs/validation.rb +15 -2
- data/lib/brs/version.rb +1 -1
- metadata +20 -19
@@ -5,17 +5,20 @@
|
|
5
5
|
#define BRS_EXT_STREAM_COMPRESSOR_H
|
6
6
|
|
7
7
|
#include <brotli/encode.h>
|
8
|
-
#include <
|
8
|
+
#include <stdbool.h>
|
9
9
|
#include <stdlib.h>
|
10
10
|
|
11
|
+
#include "brs_ext/common.h"
|
11
12
|
#include "ruby.h"
|
12
13
|
|
13
|
-
typedef struct
|
14
|
+
typedef struct
|
15
|
+
{
|
14
16
|
BrotliEncoderState* 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_compressor_t;
|
20
23
|
|
21
24
|
VALUE brs_ext_allocate_compressor(VALUE klass);
|
@@ -4,15 +4,15 @@
|
|
4
4
|
#include "brs_ext/stream/decompressor.h"
|
5
5
|
|
6
6
|
#include <brotli/decode.h>
|
7
|
-
#include <stdint.h>
|
8
|
-
#include <stdlib.h>
|
9
7
|
|
10
8
|
#include "brs_ext/buffer.h"
|
11
|
-
#include "brs_ext/common.h"
|
12
9
|
#include "brs_ext/error.h"
|
10
|
+
#include "brs_ext/gvl.h"
|
13
11
|
#include "brs_ext/option.h"
|
14
12
|
#include "ruby.h"
|
15
13
|
|
14
|
+
// -- initialization --
|
15
|
+
|
16
16
|
static void free_decompressor(brs_ext_decompressor_t* decompressor_ptr)
|
17
17
|
{
|
18
18
|
BrotliDecoderState* state_ptr = decompressor_ptr->state_ptr;
|
@@ -20,7 +20,7 @@ static void free_decompressor(brs_ext_decompressor_t* decompressor_ptr)
|
|
20
20
|
BrotliDecoderDestroyInstance(state_ptr);
|
21
21
|
}
|
22
22
|
|
23
|
-
|
23
|
+
brs_ext_byte_t* destination_buffer = decompressor_ptr->destination_buffer;
|
24
24
|
if (destination_buffer != NULL) {
|
25
25
|
free(destination_buffer);
|
26
26
|
}
|
@@ -31,7 +31,6 @@ static void free_decompressor(brs_ext_decompressor_t* decompressor_ptr)
|
|
31
31
|
VALUE brs_ext_allocate_decompressor(VALUE klass)
|
32
32
|
{
|
33
33
|
brs_ext_decompressor_t* decompressor_ptr;
|
34
|
-
|
35
34
|
VALUE self = Data_Make_Struct(klass, brs_ext_decompressor_t, NULL, free_decompressor, decompressor_ptr);
|
36
35
|
|
37
36
|
decompressor_ptr->state_ptr = NULL;
|
@@ -51,8 +50,9 @@ VALUE brs_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
51
50
|
{
|
52
51
|
GET_DECOMPRESSOR(self);
|
53
52
|
Check_Type(options, T_HASH);
|
53
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
54
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
54
55
|
BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
55
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
56
56
|
|
57
57
|
BrotliDecoderState* state_ptr = BrotliDecoderCreateInstance(NULL, NULL, NULL);
|
58
58
|
if (state_ptr == NULL) {
|
@@ -69,7 +69,7 @@ VALUE brs_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
69
69
|
destination_buffer_length = BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR;
|
70
70
|
}
|
71
71
|
|
72
|
-
|
72
|
+
brs_ext_byte_t* destination_buffer = malloc(destination_buffer_length);
|
73
73
|
if (destination_buffer == NULL) {
|
74
74
|
BrotliDecoderDestroyInstance(state_ptr);
|
75
75
|
brs_ext_raise_error(BRS_EXT_ERROR_ALLOCATE_FAILED);
|
@@ -80,62 +80,87 @@ VALUE brs_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
80
80
|
decompressor_ptr->destination_buffer_length = destination_buffer_length;
|
81
81
|
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
82
82
|
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
83
|
+
decompressor_ptr->gvl = gvl;
|
83
84
|
|
84
85
|
return Qnil;
|
85
86
|
}
|
86
87
|
|
88
|
+
// -- decompress --
|
89
|
+
|
87
90
|
#define DO_NOT_USE_AFTER_CLOSE(decompressor_ptr) \
|
88
91
|
if (decompressor_ptr->state_ptr == NULL || decompressor_ptr->destination_buffer == NULL) { \
|
89
92
|
brs_ext_raise_error(BRS_EXT_ERROR_USED_AFTER_CLOSE); \
|
90
93
|
}
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
const
|
96
|
-
size_t
|
97
|
-
|
98
|
-
|
95
|
+
typedef struct
|
96
|
+
{
|
97
|
+
brs_ext_decompressor_t* decompressor_ptr;
|
98
|
+
const brs_ext_byte_t* remaining_source;
|
99
|
+
size_t* remaining_source_length_ptr;
|
100
|
+
BrotliDecoderResult result;
|
101
|
+
} decompress_args_t;
|
102
|
+
|
103
|
+
static inline void* decompress_wrapper(void* data)
|
104
|
+
{
|
105
|
+
decompress_args_t* args = data;
|
106
|
+
brs_ext_decompressor_t* decompressor_ptr = args->decompressor_ptr;
|
107
|
+
|
108
|
+
args->result = BrotliDecoderDecompressStream(
|
109
|
+
decompressor_ptr->state_ptr,
|
110
|
+
args->remaining_source_length_ptr,
|
111
|
+
&args->remaining_source,
|
112
|
+
&decompressor_ptr->remaining_destination_buffer_length,
|
113
|
+
&decompressor_ptr->remaining_destination_buffer,
|
114
|
+
NULL);
|
115
|
+
|
116
|
+
return NULL;
|
117
|
+
}
|
99
118
|
|
100
119
|
VALUE brs_ext_decompress(VALUE self, VALUE source_value)
|
101
120
|
{
|
102
121
|
GET_DECOMPRESSOR(self);
|
103
122
|
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
104
|
-
|
123
|
+
Check_Type(source_value, T_STRING);
|
105
124
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
125
|
+
const char* source = RSTRING_PTR(source_value);
|
126
|
+
size_t source_length = RSTRING_LEN(source_value);
|
127
|
+
const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
|
128
|
+
size_t remaining_source_length = source_length;
|
129
|
+
|
130
|
+
decompress_args_t args = {
|
131
|
+
.decompressor_ptr = decompressor_ptr,
|
132
|
+
.remaining_source = remaining_source,
|
133
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
134
|
+
|
135
|
+
BRS_EXT_GVL_WRAP(decompressor_ptr->gvl, decompress_wrapper, &args);
|
111
136
|
|
112
137
|
if (
|
113
|
-
result != BROTLI_DECODER_RESULT_SUCCESS &&
|
114
|
-
result !=
|
115
|
-
result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
138
|
+
args.result != BROTLI_DECODER_RESULT_SUCCESS && args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT &&
|
139
|
+
args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
116
140
|
BrotliDecoderErrorCode error_code = BrotliDecoderGetErrorCode(decompressor_ptr->state_ptr);
|
117
141
|
brs_ext_raise_error(brs_ext_get_decompressor_error(error_code));
|
118
142
|
}
|
119
143
|
|
120
144
|
VALUE bytes_read = SIZET2NUM(source_length - remaining_source_length);
|
121
|
-
VALUE needs_more_destination = result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT ? Qtrue : Qfalse;
|
145
|
+
VALUE needs_more_destination = args.result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT ? Qtrue : Qfalse;
|
122
146
|
|
123
147
|
return rb_ary_new_from_args(2, bytes_read, needs_more_destination);
|
124
148
|
}
|
125
149
|
|
150
|
+
// -- other --
|
151
|
+
|
126
152
|
VALUE brs_ext_decompressor_read_result(VALUE self)
|
127
153
|
{
|
128
154
|
GET_DECOMPRESSOR(self);
|
129
155
|
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
130
156
|
|
131
|
-
|
132
|
-
size_t
|
133
|
-
size_t
|
157
|
+
brs_ext_byte_t* destination_buffer = decompressor_ptr->destination_buffer;
|
158
|
+
size_t destination_buffer_length = decompressor_ptr->destination_buffer_length;
|
159
|
+
size_t remaining_destination_buffer_length = decompressor_ptr->remaining_destination_buffer_length;
|
134
160
|
|
135
|
-
const char* result = (const char*)destination_buffer;
|
161
|
+
const char* result = (const char*) destination_buffer;
|
136
162
|
size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
|
137
|
-
|
138
|
-
VALUE result_value = rb_str_new(result, result_length);
|
163
|
+
VALUE result_value = rb_str_new(result, result_length);
|
139
164
|
|
140
165
|
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
141
166
|
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
@@ -143,6 +168,8 @@ VALUE brs_ext_decompressor_read_result(VALUE self)
|
|
143
168
|
return result_value;
|
144
169
|
}
|
145
170
|
|
171
|
+
// -- cleanup --
|
172
|
+
|
146
173
|
VALUE brs_ext_decompressor_close(VALUE self)
|
147
174
|
{
|
148
175
|
GET_DECOMPRESSOR(self);
|
@@ -155,7 +182,7 @@ VALUE brs_ext_decompressor_close(VALUE self)
|
|
155
182
|
decompressor_ptr->state_ptr = NULL;
|
156
183
|
}
|
157
184
|
|
158
|
-
|
185
|
+
brs_ext_byte_t* destination_buffer = decompressor_ptr->destination_buffer;
|
159
186
|
if (destination_buffer != NULL) {
|
160
187
|
free(destination_buffer);
|
161
188
|
|
@@ -168,6 +195,8 @@ VALUE brs_ext_decompressor_close(VALUE self)
|
|
168
195
|
return Qnil;
|
169
196
|
}
|
170
197
|
|
198
|
+
// -- exports --
|
199
|
+
|
171
200
|
void brs_ext_decompressor_exports(VALUE root_module)
|
172
201
|
{
|
173
202
|
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 <
|
8
|
+
#include <stdbool.h>
|
9
9
|
#include <stdlib.h>
|
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
@@ -6,12 +6,11 @@
|
|
6
6
|
#include <brotli/decode.h>
|
7
7
|
#include <brotli/encode.h>
|
8
8
|
#include <brotli/types.h>
|
9
|
-
#include <stdint.h>
|
10
9
|
#include <stdlib.h>
|
11
10
|
|
12
11
|
#include "brs_ext/buffer.h"
|
13
|
-
#include "brs_ext/common.h"
|
14
12
|
#include "brs_ext/error.h"
|
13
|
+
#include "brs_ext/gvl.h"
|
15
14
|
#include "brs_ext/macro.h"
|
16
15
|
#include "brs_ext/option.h"
|
17
16
|
#include "ruby.h"
|
@@ -19,8 +18,10 @@
|
|
19
18
|
// -- buffer --
|
20
19
|
|
21
20
|
static inline brs_ext_result_t increase_destination_buffer(
|
22
|
-
VALUE
|
23
|
-
size_t
|
21
|
+
VALUE destination_value,
|
22
|
+
size_t destination_length,
|
23
|
+
size_t* remaining_destination_buffer_length_ptr,
|
24
|
+
size_t destination_buffer_length)
|
24
25
|
{
|
25
26
|
if (*remaining_destination_buffer_length_ptr == destination_buffer_length) {
|
26
27
|
// We want to write more data at once, than buffer has.
|
@@ -39,42 +40,63 @@ static inline brs_ext_result_t increase_destination_buffer(
|
|
39
40
|
return 0;
|
40
41
|
}
|
41
42
|
|
42
|
-
// -- utils --
|
43
|
-
|
44
|
-
#define GET_SOURCE_DATA(source_value) \
|
45
|
-
Check_Type(source_value, T_STRING); \
|
46
|
-
\
|
47
|
-
const char* source = RSTRING_PTR(source_value); \
|
48
|
-
size_t source_length = RSTRING_LEN(source_value);
|
49
|
-
|
50
43
|
// -- compress --
|
51
44
|
|
45
|
+
typedef struct
|
46
|
+
{
|
47
|
+
BrotliEncoderState* state_ptr;
|
48
|
+
const brs_ext_byte_t** remaining_source_ptr;
|
49
|
+
size_t* remaining_source_length_ptr;
|
50
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
51
|
+
size_t* remaining_destination_buffer_length_ptr;
|
52
|
+
BROTLI_BOOL result;
|
53
|
+
} compress_args_t;
|
54
|
+
|
55
|
+
static inline void* compress_wrapper(void* data)
|
56
|
+
{
|
57
|
+
compress_args_t* args = data;
|
58
|
+
|
59
|
+
args->result = BrotliEncoderCompressStream(
|
60
|
+
args->state_ptr,
|
61
|
+
BROTLI_OPERATION_FINISH,
|
62
|
+
args->remaining_source_length_ptr,
|
63
|
+
args->remaining_source_ptr,
|
64
|
+
args->remaining_destination_buffer_length_ptr,
|
65
|
+
&args->remaining_destination_buffer,
|
66
|
+
NULL);
|
67
|
+
|
68
|
+
return NULL;
|
69
|
+
}
|
70
|
+
|
52
71
|
static inline brs_ext_result_t compress(
|
53
72
|
BrotliEncoderState* state_ptr,
|
54
|
-
const char*
|
55
|
-
|
73
|
+
const char* source,
|
74
|
+
size_t source_length,
|
75
|
+
VALUE destination_value,
|
76
|
+
size_t destination_buffer_length,
|
77
|
+
bool gvl)
|
56
78
|
{
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
size_t
|
79
|
+
brs_ext_result_t ext_result;
|
80
|
+
const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
|
81
|
+
size_t remaining_source_length = source_length;
|
82
|
+
size_t destination_length = 0;
|
83
|
+
size_t remaining_destination_buffer_length = destination_buffer_length;
|
62
84
|
|
63
|
-
|
64
|
-
|
85
|
+
compress_args_t args = {
|
86
|
+
.state_ptr = state_ptr,
|
87
|
+
.remaining_source_ptr = &remaining_source,
|
88
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
65
89
|
|
66
90
|
while (true) {
|
67
|
-
|
68
|
-
|
91
|
+
brs_ext_byte_t* remaining_destination_buffer =
|
92
|
+
(brs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
|
93
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
69
94
|
|
70
|
-
|
71
|
-
|
72
|
-
BROTLI_OPERATION_FINISH,
|
73
|
-
&remaining_source_length, &remaining_source,
|
74
|
-
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
75
|
-
NULL);
|
95
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
96
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
76
97
|
|
77
|
-
|
98
|
+
BRS_EXT_GVL_WRAP(gvl, compress_wrapper, &args);
|
99
|
+
if (!args.result) {
|
78
100
|
return BRS_EXT_ERROR_UNEXPECTED;
|
79
101
|
}
|
80
102
|
|
@@ -82,8 +104,7 @@ static inline brs_ext_result_t compress(
|
|
82
104
|
|
83
105
|
if (BrotliEncoderHasMoreOutput(state_ptr) || !BrotliEncoderIsFinished(state_ptr)) {
|
84
106
|
ext_result = increase_destination_buffer(
|
85
|
-
destination_value, destination_length,
|
86
|
-
&remaining_destination_buffer_length, destination_buffer_length);
|
107
|
+
destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
|
87
108
|
|
88
109
|
if (ext_result != 0) {
|
89
110
|
return ext_result;
|
@@ -107,10 +128,11 @@ static inline brs_ext_result_t compress(
|
|
107
128
|
|
108
129
|
VALUE brs_ext_compress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VALUE options)
|
109
130
|
{
|
110
|
-
|
131
|
+
Check_Type(source_value, T_STRING);
|
111
132
|
Check_Type(options, T_HASH);
|
133
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
134
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
112
135
|
BRS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
113
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
114
136
|
|
115
137
|
BrotliEncoderState* state_ptr = BrotliEncoderCreateInstance(NULL, NULL, NULL);
|
116
138
|
if (state_ptr == NULL) {
|
@@ -135,10 +157,10 @@ VALUE brs_ext_compress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VA
|
|
135
157
|
brs_ext_raise_error(BRS_EXT_ERROR_ALLOCATE_FAILED);
|
136
158
|
}
|
137
159
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
160
|
+
const char* source = RSTRING_PTR(source_value);
|
161
|
+
size_t source_length = RSTRING_LEN(source_value);
|
162
|
+
|
163
|
+
ext_result = compress(state_ptr, source, source_length, destination_value, destination_buffer_length, gvl);
|
142
164
|
|
143
165
|
BrotliEncoderDestroyInstance(state_ptr);
|
144
166
|
|
@@ -151,44 +173,71 @@ VALUE brs_ext_compress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VA
|
|
151
173
|
|
152
174
|
// -- decompress --
|
153
175
|
|
176
|
+
typedef struct
|
177
|
+
{
|
178
|
+
BrotliDecoderState* state_ptr;
|
179
|
+
const brs_ext_byte_t** remaining_source_ptr;
|
180
|
+
size_t* remaining_source_length_ptr;
|
181
|
+
brs_ext_byte_t* remaining_destination_buffer;
|
182
|
+
size_t* remaining_destination_buffer_length_ptr;
|
183
|
+
brs_ext_result_t result;
|
184
|
+
} decompress_args_t;
|
185
|
+
|
186
|
+
static inline void* decompress_wrapper(void* data)
|
187
|
+
{
|
188
|
+
decompress_args_t* args = data;
|
189
|
+
|
190
|
+
args->result = BrotliDecoderDecompressStream(
|
191
|
+
args->state_ptr,
|
192
|
+
args->remaining_source_length_ptr,
|
193
|
+
args->remaining_source_ptr,
|
194
|
+
args->remaining_destination_buffer_length_ptr,
|
195
|
+
&args->remaining_destination_buffer,
|
196
|
+
NULL);
|
197
|
+
|
198
|
+
return NULL;
|
199
|
+
}
|
200
|
+
|
154
201
|
static inline brs_ext_result_t decompress(
|
155
202
|
BrotliDecoderState* state_ptr,
|
156
|
-
const char*
|
157
|
-
|
203
|
+
const char* source,
|
204
|
+
size_t source_length,
|
205
|
+
VALUE destination_value,
|
206
|
+
size_t destination_buffer_length,
|
207
|
+
bool gvl)
|
158
208
|
{
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
size_t
|
209
|
+
brs_ext_result_t ext_result;
|
210
|
+
const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
|
211
|
+
size_t remaining_source_length = source_length;
|
212
|
+
size_t destination_length = 0;
|
213
|
+
size_t remaining_destination_buffer_length = destination_buffer_length;
|
164
214
|
|
165
|
-
|
166
|
-
|
215
|
+
decompress_args_t args = {
|
216
|
+
.state_ptr = state_ptr,
|
217
|
+
.remaining_source_ptr = &remaining_source,
|
218
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
167
219
|
|
168
220
|
while (true) {
|
169
|
-
|
170
|
-
|
221
|
+
brs_ext_byte_t* remaining_destination_buffer =
|
222
|
+
(brs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
|
223
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
171
224
|
|
172
|
-
|
173
|
-
|
174
|
-
&remaining_source_length, &remaining_source,
|
175
|
-
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
176
|
-
NULL);
|
225
|
+
args.remaining_destination_buffer = remaining_destination_buffer;
|
226
|
+
args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
|
177
227
|
|
228
|
+
BRS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
|
178
229
|
if (
|
179
|
-
result != BROTLI_DECODER_RESULT_SUCCESS &&
|
180
|
-
result !=
|
181
|
-
result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
230
|
+
args.result != BROTLI_DECODER_RESULT_SUCCESS && args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT &&
|
231
|
+
args.result != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
182
232
|
BrotliDecoderErrorCode error_code = BrotliDecoderGetErrorCode(state_ptr);
|
183
233
|
return brs_ext_get_decompressor_error(error_code);
|
184
234
|
}
|
185
235
|
|
186
236
|
destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length;
|
187
237
|
|
188
|
-
if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
238
|
+
if (args.result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
189
239
|
ext_result = increase_destination_buffer(
|
190
|
-
destination_value, destination_length,
|
191
|
-
&remaining_destination_buffer_length, destination_buffer_length);
|
240
|
+
destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
|
192
241
|
|
193
242
|
if (ext_result != 0) {
|
194
243
|
return ext_result;
|
@@ -212,10 +261,11 @@ static inline brs_ext_result_t decompress(
|
|
212
261
|
|
213
262
|
VALUE brs_ext_decompress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value, VALUE options)
|
214
263
|
{
|
215
|
-
|
264
|
+
Check_Type(source_value, T_STRING);
|
216
265
|
Check_Type(options, T_HASH);
|
266
|
+
BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
267
|
+
BRS_EXT_GET_BOOL_OPTION(options, gvl);
|
217
268
|
BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
218
|
-
BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
219
269
|
|
220
270
|
BrotliDecoderState* state_ptr = BrotliDecoderCreateInstance(NULL, NULL, NULL);
|
221
271
|
if (state_ptr == NULL) {
|
@@ -240,10 +290,10 @@ VALUE brs_ext_decompress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value,
|
|
240
290
|
brs_ext_raise_error(BRS_EXT_ERROR_ALLOCATE_FAILED);
|
241
291
|
}
|
242
292
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
293
|
+
const char* source = RSTRING_PTR(source_value);
|
294
|
+
size_t source_length = RSTRING_LEN(source_value);
|
295
|
+
|
296
|
+
ext_result = decompress(state_ptr, source, source_length, destination_value, destination_buffer_length, gvl);
|
247
297
|
|
248
298
|
BrotliDecoderDestroyInstance(state_ptr);
|
249
299
|
|
@@ -254,6 +304,8 @@ VALUE brs_ext_decompress_string(VALUE BRS_EXT_UNUSED(self), VALUE source_value,
|
|
254
304
|
return destination_value;
|
255
305
|
}
|
256
306
|
|
307
|
+
// -- exports --
|
308
|
+
|
257
309
|
void brs_ext_string_exports(VALUE root_module)
|
258
310
|
{
|
259
311
|
rb_define_module_function(root_module, "_native_compress_string", RUBY_METHOD_FUNC(brs_ext_compress_string), 2);
|