ruby-brs 1.1.2 → 1.2.1

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