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.
@@ -2,7 +2,6 @@
2
2
  // Copyright (c) 2019 AUTHORS, MIT License.
3
3
 
4
4
  #include "brs_ext/buffer.h"
5
- #include "brs_ext/common.h"
6
5
  #include "brs_ext/io.h"
7
6
  #include "brs_ext/option.h"
8
7
  #include "brs_ext/stream/compressor.h"
@@ -5,21 +5,18 @@
5
5
 
6
6
  #include <brotli/decode.h>
7
7
  #include <brotli/encode.h>
8
- #include <stdbool.h>
9
- #include <stdlib.h>
10
8
 
11
- #include "brs_ext/common.h"
12
9
  #include "brs_ext/error.h"
13
10
  #include "ruby.h"
14
11
 
15
12
  // -- values --
16
13
 
17
- static inline VALUE get_raw_option_value(VALUE options, const char* name)
14
+ static inline VALUE get_raw_value(VALUE options, const char* name)
18
15
  {
19
16
  return rb_funcall(options, rb_intern("[]"), 1, ID2SYM(rb_intern(name)));
20
17
  }
21
18
 
22
- static inline bool get_bool_option_value(VALUE raw_value)
19
+ static inline bool get_bool_value(VALUE raw_value)
23
20
  {
24
21
  int raw_type = TYPE(raw_value);
25
22
  if (raw_type != T_TRUE && raw_type != T_FALSE) {
@@ -29,35 +26,39 @@ static inline bool get_bool_option_value(VALUE raw_value)
29
26
  return raw_type == T_TRUE;
30
27
  }
31
28
 
32
- static inline unsigned int get_uint_option_value(VALUE raw_value)
29
+ static inline unsigned int get_uint_value(VALUE raw_value)
33
30
  {
34
31
  Check_Type(raw_value, T_FIXNUM);
35
32
 
36
33
  return NUM2UINT(raw_value);
37
34
  }
38
35
 
39
- static inline BrotliEncoderMode get_mode_option_value(VALUE raw_value)
36
+ static inline size_t get_size_value(VALUE raw_value)
37
+ {
38
+ Check_Type(raw_value, T_FIXNUM);
39
+
40
+ return NUM2SIZET(raw_value);
41
+ }
42
+
43
+ static inline BrotliEncoderMode get_mode_value(VALUE raw_value)
40
44
  {
41
45
  Check_Type(raw_value, T_SYMBOL);
42
46
 
43
47
  ID raw_id = SYM2ID(raw_value);
44
48
  if (raw_id == rb_intern("text")) {
45
49
  return BROTLI_MODE_TEXT;
46
- }
47
- else if (raw_id == rb_intern("font")) {
50
+ } else if (raw_id == rb_intern("font")) {
48
51
  return BROTLI_MODE_FONT;
49
- }
50
- else if (raw_id == rb_intern("generic")) {
52
+ } else if (raw_id == rb_intern("generic")) {
51
53
  return BROTLI_MODE_GENERIC;
52
- }
53
- else {
54
+ } else {
54
55
  brs_ext_raise_error(BRS_EXT_ERROR_VALIDATE_FAILED);
55
56
  }
56
57
  }
57
58
 
58
- void brs_ext_get_option(VALUE options, brs_ext_option_t* option, brs_ext_option_type_t type, const char* name)
59
+ void brs_ext_resolve_option(VALUE options, brs_ext_option_t* option, brs_ext_option_type_t type, const char* name)
59
60
  {
60
- VALUE raw_value = get_raw_option_value(options, name);
61
+ VALUE raw_value = get_raw_value(options, name);
61
62
 
62
63
  option->has_value = raw_value != Qnil;
63
64
  if (!option->has_value) {
@@ -68,13 +69,13 @@ void brs_ext_get_option(VALUE options, brs_ext_option_t* option, brs_ext_option_
68
69
 
69
70
  switch (type) {
70
71
  case BRS_EXT_OPTION_TYPE_BOOL:
71
- value = get_bool_option_value(raw_value) ? 1 : 0;
72
+ value = get_bool_value(raw_value) ? 1 : 0;
72
73
  break;
73
74
  case BRS_EXT_OPTION_TYPE_UINT:
74
- value = (brs_ext_option_value_t)get_uint_option_value(raw_value);
75
+ value = (brs_ext_option_value_t) get_uint_value(raw_value);
75
76
  break;
76
77
  case BRS_EXT_OPTION_TYPE_MODE:
77
- value = (brs_ext_option_value_t)get_mode_option_value(raw_value);
78
+ value = (brs_ext_option_value_t) get_mode_value(raw_value);
78
79
  break;
79
80
  default:
80
81
  brs_ext_raise_error(BRS_EXT_ERROR_UNEXPECTED);
@@ -83,13 +84,18 @@ void brs_ext_get_option(VALUE options, brs_ext_option_t* option, brs_ext_option_
83
84
  option->value = value;
84
85
  }
85
86
 
86
- size_t brs_ext_get_size_option_value(VALUE options, const char* name)
87
+ bool brs_ext_get_bool_option_value(VALUE options, const char* name)
87
88
  {
88
- VALUE raw_value = get_raw_option_value(options, name);
89
+ VALUE raw_value = get_raw_value(options, name);
89
90
 
90
- Check_Type(raw_value, T_FIXNUM);
91
+ return get_bool_value(raw_value);
92
+ }
91
93
 
92
- return NUM2SIZET(raw_value);
94
+ size_t brs_ext_get_size_option_value(VALUE options, const char* name)
95
+ {
96
+ VALUE raw_value = get_raw_value(options, name);
97
+
98
+ return get_size_value(raw_value);
93
99
  }
94
100
 
95
101
  // -- set params --
@@ -108,7 +114,8 @@ brs_ext_result_t brs_ext_set_compressor_options(BrotliEncoderState* state_ptr, b
108
114
  SET_ENCODER_PARAM(state_ptr, BROTLI_PARAM_QUALITY, options->quality);
109
115
  SET_ENCODER_PARAM(state_ptr, BROTLI_PARAM_LGWIN, options->lgwin);
110
116
  SET_ENCODER_PARAM(state_ptr, BROTLI_PARAM_LGBLOCK, options->lgblock);
111
- SET_ENCODER_PARAM(state_ptr, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, options->disable_literal_context_modeling);
117
+ SET_ENCODER_PARAM(
118
+ state_ptr, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, options->disable_literal_context_modeling);
112
119
  SET_ENCODER_PARAM(state_ptr, BROTLI_PARAM_SIZE_HINT, options->size_hint);
113
120
  SET_ENCODER_PARAM(state_ptr, BROTLI_PARAM_LARGE_WINDOW, options->large_window);
114
121
 
@@ -118,9 +125,12 @@ brs_ext_result_t brs_ext_set_compressor_options(BrotliEncoderState* state_ptr, b
118
125
  #define SET_DECODER_PARAM(state_ptr, param, option) \
119
126
  SET_OPTION_VALUE(BrotliDecoderSetParameter, state_ptr, param, option);
120
127
 
121
- brs_ext_result_t brs_ext_set_decompressor_options(BrotliDecoderState* state_ptr, brs_ext_decompressor_options_t* options)
128
+ brs_ext_result_t brs_ext_set_decompressor_options(
129
+ BrotliDecoderState* state_ptr,
130
+ brs_ext_decompressor_options_t* options)
122
131
  {
123
- SET_DECODER_PARAM(state_ptr, BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION, options->disable_ring_buffer_reallocation);
132
+ SET_DECODER_PARAM(
133
+ state_ptr, BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION, options->disable_ring_buffer_reallocation);
124
134
  SET_DECODER_PARAM(state_ptr, BROTLI_DECODER_PARAM_LARGE_WINDOW, options->large_window);
125
135
 
126
136
  return 0;
@@ -136,11 +146,8 @@ void brs_ext_option_exports(VALUE root_module)
136
146
  {
137
147
  VALUE module = rb_define_module_under(root_module, "Option");
138
148
 
139
- VALUE modes = rb_ary_new_from_args(
140
- 3,
141
- ID2SYM(rb_intern("text")),
142
- ID2SYM(rb_intern("font")),
143
- ID2SYM(rb_intern("generic")));
149
+ VALUE modes =
150
+ rb_ary_new_from_args(3, ID2SYM(rb_intern("text")), ID2SYM(rb_intern("font")), ID2SYM(rb_intern("generic")));
144
151
  rb_define_const(module, "MODES", modes);
145
152
  RB_GC_GUARD(modes);
146
153
 
@@ -7,7 +7,6 @@
7
7
  #include <brotli/decode.h>
8
8
  #include <brotli/encode.h>
9
9
  #include <stdbool.h>
10
- #include <stdint.h>
11
10
  #include <stdlib.h>
12
11
 
13
12
  #include "brs_ext/common.h"
@@ -16,21 +15,24 @@
16
15
  // Default option values depends on brotli library.
17
16
  // We will set only user defined values.
18
17
 
19
- enum {
18
+ enum
19
+ {
20
20
  BRS_EXT_OPTION_TYPE_BOOL = 1,
21
21
  BRS_EXT_OPTION_TYPE_UINT,
22
22
  BRS_EXT_OPTION_TYPE_MODE
23
23
  };
24
24
 
25
- typedef uint_fast8_t brs_ext_option_type_t;
26
- typedef uint32_t brs_ext_option_value_t;
25
+ typedef brs_ext_byte_fast_t brs_ext_option_type_t;
26
+ typedef uint32_t brs_ext_option_value_t;
27
27
 
28
- typedef struct {
28
+ typedef struct
29
+ {
29
30
  bool has_value;
30
31
  brs_ext_option_value_t value;
31
32
  } brs_ext_option_t;
32
33
 
33
- typedef struct {
34
+ typedef struct
35
+ {
34
36
  brs_ext_option_t mode;
35
37
  brs_ext_option_t quality;
36
38
  brs_ext_option_t lgwin;
@@ -40,40 +42,45 @@ typedef struct {
40
42
  brs_ext_option_t large_window;
41
43
  } brs_ext_compressor_options_t;
42
44
 
43
- typedef struct {
45
+ typedef struct
46
+ {
44
47
  brs_ext_option_t disable_ring_buffer_reallocation;
45
48
  brs_ext_option_t large_window;
46
49
  } brs_ext_decompressor_options_t;
47
50
 
48
- void brs_ext_get_option(VALUE options, brs_ext_option_t* option, brs_ext_option_type_t type, const char* name);
49
-
50
- #define BRS_EXT_GET_OPTION(options, target_options, type, name) \
51
- brs_ext_get_option(options, &target_options.name, type, #name);
52
-
53
- #define BRS_EXT_GET_COMPRESSOR_OPTIONS(options) \
54
- brs_ext_compressor_options_t compressor_options; \
55
- \
56
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_MODE, mode); \
57
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, quality); \
58
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, lgwin); \
59
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, lgblock); \
60
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_BOOL, disable_literal_context_modeling); \
61
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, size_hint); \
62
- BRS_EXT_GET_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_BOOL, large_window);
63
-
64
- #define BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options) \
65
- brs_ext_decompressor_options_t decompressor_options; \
66
- \
67
- BRS_EXT_GET_OPTION(options, decompressor_options, BRS_EXT_OPTION_TYPE_BOOL, disable_ring_buffer_reallocation); \
68
- BRS_EXT_GET_OPTION(options, decompressor_options, BRS_EXT_OPTION_TYPE_BOOL, large_window);
69
-
51
+ void brs_ext_resolve_option(VALUE options, brs_ext_option_t* option, brs_ext_option_type_t type, const char* name);
52
+
53
+ #define BRS_EXT_RESOLVE_OPTION(options, target_options, type, name) \
54
+ brs_ext_resolve_option(options, &target_options.name, type, #name);
55
+
56
+ #define BRS_EXT_GET_COMPRESSOR_OPTIONS(options) \
57
+ brs_ext_compressor_options_t compressor_options; \
58
+ \
59
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_MODE, mode); \
60
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, quality); \
61
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, lgwin); \
62
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, lgblock); \
63
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_BOOL, disable_literal_context_modeling); \
64
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_UINT, size_hint); \
65
+ BRS_EXT_RESOLVE_OPTION(options, compressor_options, BRS_EXT_OPTION_TYPE_BOOL, large_window);
66
+
67
+ #define BRS_EXT_GET_DECOMPRESSOR_OPTIONS(options) \
68
+ brs_ext_decompressor_options_t decompressor_options; \
69
+ \
70
+ BRS_EXT_RESOLVE_OPTION(options, decompressor_options, BRS_EXT_OPTION_TYPE_BOOL, disable_ring_buffer_reallocation); \
71
+ BRS_EXT_RESOLVE_OPTION(options, decompressor_options, BRS_EXT_OPTION_TYPE_BOOL, large_window);
72
+
73
+ bool brs_ext_get_bool_option_value(VALUE options, const char* name);
70
74
  size_t brs_ext_get_size_option_value(VALUE options, const char* name);
71
75
 
72
- #define BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, name) \
73
- size_t name = brs_ext_get_size_option_value(options, #name);
76
+ #define BRS_EXT_GET_BOOL_OPTION(options, name) size_t name = brs_ext_get_bool_option_value(options, #name);
77
+ #define BRS_EXT_GET_SIZE_OPTION(options, name) size_t name = brs_ext_get_size_option_value(options, #name);
74
78
 
75
79
  brs_ext_result_t brs_ext_set_compressor_options(BrotliEncoderState* state_ptr, brs_ext_compressor_options_t* options);
76
- brs_ext_result_t brs_ext_set_decompressor_options(BrotliDecoderState* state_ptr, brs_ext_decompressor_options_t* options);
80
+
81
+ brs_ext_result_t brs_ext_set_decompressor_options(
82
+ BrotliDecoderState* state_ptr,
83
+ brs_ext_decompressor_options_t* options);
77
84
 
78
85
  void brs_ext_option_exports(VALUE root_module);
79
86
 
@@ -5,15 +5,15 @@
5
5
 
6
6
  #include <brotli/encode.h>
7
7
  #include <brotli/types.h>
8
- #include <stdint.h>
9
- #include <stdlib.h>
10
8
 
11
9
  #include "brs_ext/buffer.h"
12
- #include "brs_ext/common.h"
13
10
  #include "brs_ext/error.h"
11
+ #include "brs_ext/gvl.h"
14
12
  #include "brs_ext/option.h"
15
13
  #include "ruby.h"
16
14
 
15
+ // -- initialization --
16
+
17
17
  static void free_compressor(brs_ext_compressor_t* compressor_ptr)
18
18
  {
19
19
  BrotliEncoderState* state_ptr = compressor_ptr->state_ptr;
@@ -21,7 +21,7 @@ static void free_compressor(brs_ext_compressor_t* compressor_ptr)
21
21
  BrotliEncoderDestroyInstance(state_ptr);
22
22
  }
23
23
 
24
- uint8_t* destination_buffer = compressor_ptr->destination_buffer;
24
+ brs_ext_byte_t* destination_buffer = compressor_ptr->destination_buffer;
25
25
  if (destination_buffer != NULL) {
26
26
  free(destination_buffer);
27
27
  }
@@ -32,14 +32,14 @@ static void free_compressor(brs_ext_compressor_t* compressor_ptr)
32
32
  VALUE brs_ext_allocate_compressor(VALUE klass)
33
33
  {
34
34
  brs_ext_compressor_t* compressor_ptr;
35
-
36
- VALUE self = Data_Make_Struct(klass, brs_ext_compressor_t, NULL, free_compressor, compressor_ptr);
35
+ VALUE self = Data_Make_Struct(klass, brs_ext_compressor_t, NULL, free_compressor, compressor_ptr);
37
36
 
38
37
  compressor_ptr->state_ptr = NULL;
39
38
  compressor_ptr->destination_buffer = NULL;
40
39
  compressor_ptr->destination_buffer_length = 0;
41
40
  compressor_ptr->remaining_destination_buffer = NULL;
42
41
  compressor_ptr->remaining_destination_buffer_length = 0;
42
+ compressor_ptr->gvl = false;
43
43
 
44
44
  return self;
45
45
  }
@@ -52,8 +52,9 @@ VALUE brs_ext_initialize_compressor(VALUE self, VALUE options)
52
52
  {
53
53
  GET_COMPRESSOR(self);
54
54
  Check_Type(options, T_HASH);
55
+ BRS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
56
+ BRS_EXT_GET_BOOL_OPTION(options, gvl);
55
57
  BRS_EXT_GET_COMPRESSOR_OPTIONS(options);
56
- BRS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
57
58
 
58
59
  BrotliEncoderState* state_ptr = BrotliEncoderCreateInstance(NULL, NULL, NULL);
59
60
  if (state_ptr == NULL) {
@@ -70,7 +71,7 @@ VALUE brs_ext_initialize_compressor(VALUE self, VALUE options)
70
71
  destination_buffer_length = BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR;
71
72
  }
72
73
 
73
- uint8_t* destination_buffer = malloc(destination_buffer_length);
74
+ brs_ext_byte_t* destination_buffer = malloc(destination_buffer_length);
74
75
  if (destination_buffer == NULL) {
75
76
  BrotliEncoderDestroyInstance(state_ptr);
76
77
  brs_ext_raise_error(BRS_EXT_ERROR_ALLOCATE_FAILED);
@@ -81,72 +82,137 @@ VALUE brs_ext_initialize_compressor(VALUE self, VALUE options)
81
82
  compressor_ptr->destination_buffer_length = destination_buffer_length;
82
83
  compressor_ptr->remaining_destination_buffer = destination_buffer;
83
84
  compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
85
+ compressor_ptr->gvl = gvl;
84
86
 
85
87
  return Qnil;
86
88
  }
87
89
 
90
+ // -- compress --
91
+
88
92
  #define DO_NOT_USE_AFTER_CLOSE(compressor_ptr) \
89
93
  if (compressor_ptr->state_ptr == NULL || compressor_ptr->destination_buffer == NULL) { \
90
94
  brs_ext_raise_error(BRS_EXT_ERROR_USED_AFTER_CLOSE); \
91
95
  }
92
96
 
93
- #define GET_SOURCE_DATA(source_value) \
94
- Check_Type(source_value, T_STRING); \
95
- \
96
- const char* source = RSTRING_PTR(source_value); \
97
- size_t source_length = RSTRING_LEN(source_value); \
98
- const uint8_t* remaining_source = (const uint8_t*)source; \
99
- size_t remaining_source_length = source_length;
97
+ typedef struct
98
+ {
99
+ brs_ext_compressor_t* compressor_ptr;
100
+ const brs_ext_byte_t* remaining_source;
101
+ size_t* remaining_source_length_ptr;
102
+ BROTLI_BOOL result;
103
+ } compress_args_t;
104
+
105
+ static inline void* compress_wrapper(void* data)
106
+ {
107
+ compress_args_t* args = data;
108
+ brs_ext_compressor_t* compressor_ptr = args->compressor_ptr;
109
+
110
+ args->result = BrotliEncoderCompressStream(
111
+ compressor_ptr->state_ptr,
112
+ BROTLI_OPERATION_PROCESS,
113
+ args->remaining_source_length_ptr,
114
+ &args->remaining_source,
115
+ &compressor_ptr->remaining_destination_buffer_length,
116
+ &compressor_ptr->remaining_destination_buffer,
117
+ NULL);
118
+
119
+ return NULL;
120
+ }
100
121
 
101
122
  VALUE brs_ext_compress(VALUE self, VALUE source_value)
102
123
  {
103
124
  GET_COMPRESSOR(self);
104
125
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
105
- GET_SOURCE_DATA(source_value);
126
+ Check_Type(source_value, T_STRING);
106
127
 
107
- BrotliEncoderState* state_ptr = compressor_ptr->state_ptr;
128
+ const char* source = RSTRING_PTR(source_value);
129
+ size_t source_length = RSTRING_LEN(source_value);
130
+ const brs_ext_byte_t* remaining_source = (const brs_ext_byte_t*) source;
131
+ size_t remaining_source_length = source_length;
108
132
 
109
- BROTLI_BOOL result = BrotliEncoderCompressStream(
110
- state_ptr,
111
- BROTLI_OPERATION_PROCESS,
112
- &remaining_source_length, &remaining_source,
113
- &compressor_ptr->remaining_destination_buffer_length, &compressor_ptr->remaining_destination_buffer,
114
- NULL);
133
+ compress_args_t args = {
134
+ .compressor_ptr = compressor_ptr,
135
+ .remaining_source = remaining_source,
136
+ .remaining_source_length_ptr = &remaining_source_length};
115
137
 
116
- if (!result) {
138
+ BRS_EXT_GVL_WRAP(compressor_ptr->gvl, compress_wrapper, &args);
139
+ if (!args.result) {
117
140
  brs_ext_raise_error(BRS_EXT_ERROR_UNEXPECTED);
118
141
  }
119
142
 
120
143
  VALUE bytes_written = SIZET2NUM(source_length - remaining_source_length);
121
- VALUE needs_more_destination = BrotliEncoderHasMoreOutput(state_ptr) ? Qtrue : Qfalse;
144
+ VALUE needs_more_destination = BrotliEncoderHasMoreOutput(compressor_ptr->state_ptr) ? Qtrue : Qfalse;
122
145
 
123
146
  return rb_ary_new_from_args(2, bytes_written, needs_more_destination);
124
147
  }
125
148
 
126
- VALUE brs_ext_flush_compressor(VALUE self)
127
- {
128
- GET_COMPRESSOR(self);
129
- DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
149
+ // -- compressor flush --
130
150
 
131
- BrotliEncoderState* state_ptr = compressor_ptr->state_ptr;
151
+ typedef struct
152
+ {
153
+ brs_ext_compressor_t* compressor_ptr;
154
+ BROTLI_BOOL result;
155
+ } compressor_flush_args_t;
132
156
 
133
- const uint8_t* remaining_source = NULL;
134
- size_t remaining_source_length = 0;
157
+ static inline void* compressor_flush_wrapper(void* data)
158
+ {
159
+ compressor_flush_args_t* args = data;
160
+ brs_ext_compressor_t* compressor_ptr = args->compressor_ptr;
161
+ const brs_ext_byte_t* remaining_source = NULL;
162
+ size_t remaining_source_length = 0;
135
163
 
136
- BROTLI_BOOL result = BrotliEncoderCompressStream(
137
- state_ptr,
164
+ args->result = BrotliEncoderCompressStream(
165
+ compressor_ptr->state_ptr,
138
166
  BROTLI_OPERATION_FLUSH,
139
- &remaining_source_length, &remaining_source,
140
- &compressor_ptr->remaining_destination_buffer_length, &compressor_ptr->remaining_destination_buffer,
167
+ &remaining_source_length,
168
+ &remaining_source,
169
+ &compressor_ptr->remaining_destination_buffer_length,
170
+ &compressor_ptr->remaining_destination_buffer,
141
171
  NULL);
142
172
 
143
- if (!result) {
173
+ return NULL;
174
+ }
175
+
176
+ VALUE brs_ext_flush_compressor(VALUE self)
177
+ {
178
+ GET_COMPRESSOR(self);
179
+ DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
180
+
181
+ compressor_flush_args_t args = {.compressor_ptr = compressor_ptr};
182
+
183
+ BRS_EXT_GVL_WRAP(compressor_ptr->gvl, compressor_flush_wrapper, &args);
184
+ if (!args.result) {
144
185
  brs_ext_raise_error(BRS_EXT_ERROR_UNEXPECTED);
145
186
  }
146
187
 
147
- VALUE needs_more_destination = BrotliEncoderHasMoreOutput(state_ptr) ? Qtrue : Qfalse;
188
+ return BrotliEncoderHasMoreOutput(compressor_ptr->state_ptr) ? Qtrue : Qfalse;
189
+ }
190
+
191
+ // -- compressor finish --
148
192
 
149
- return needs_more_destination;
193
+ typedef struct
194
+ {
195
+ brs_ext_compressor_t* compressor_ptr;
196
+ BROTLI_BOOL result;
197
+ } compressor_finish_args_t;
198
+
199
+ static inline void* compressor_finish_wrapper(void* data)
200
+ {
201
+ compressor_finish_args_t* args = data;
202
+ brs_ext_compressor_t* compressor_ptr = args->compressor_ptr;
203
+ const brs_ext_byte_t* remaining_source = NULL;
204
+ size_t remaining_source_length = 0;
205
+
206
+ args->result = BrotliEncoderCompressStream(
207
+ compressor_ptr->state_ptr,
208
+ BROTLI_OPERATION_FINISH,
209
+ &remaining_source_length,
210
+ &remaining_source,
211
+ &compressor_ptr->remaining_destination_buffer_length,
212
+ &compressor_ptr->remaining_destination_buffer,
213
+ NULL);
214
+
215
+ return NULL;
150
216
  }
151
217
 
152
218
  VALUE brs_ext_finish_compressor(VALUE self)
@@ -154,40 +220,33 @@ VALUE brs_ext_finish_compressor(VALUE self)
154
220
  GET_COMPRESSOR(self);
155
221
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
156
222
 
157
- BrotliEncoderState* state_ptr = compressor_ptr->state_ptr;
158
-
159
- const uint8_t* remaining_source = NULL;
160
- size_t remaining_source_length = 0;
161
-
162
- BROTLI_BOOL result = BrotliEncoderCompressStream(
163
- state_ptr,
164
- BROTLI_OPERATION_FINISH,
165
- &remaining_source_length, &remaining_source,
166
- &compressor_ptr->remaining_destination_buffer_length, &compressor_ptr->remaining_destination_buffer,
167
- NULL);
223
+ compressor_finish_args_t args = {.compressor_ptr = compressor_ptr};
168
224
 
169
- if (!result) {
225
+ BRS_EXT_GVL_WRAP(compressor_ptr->gvl, compressor_finish_wrapper, &args);
226
+ if (!args.result) {
170
227
  brs_ext_raise_error(BRS_EXT_ERROR_UNEXPECTED);
171
228
  }
172
229
 
173
- VALUE needs_more_destination = (BrotliEncoderHasMoreOutput(state_ptr) || !BrotliEncoderIsFinished(state_ptr)) ? Qtrue : Qfalse;
174
-
175
- return needs_more_destination;
230
+ return (BrotliEncoderHasMoreOutput(compressor_ptr->state_ptr) ||
231
+ !BrotliEncoderIsFinished(compressor_ptr->state_ptr)) ?
232
+ Qtrue :
233
+ Qfalse;
176
234
  }
177
235
 
236
+ // -- other --
237
+
178
238
  VALUE brs_ext_compressor_read_result(VALUE self)
179
239
  {
180
240
  GET_COMPRESSOR(self);
181
241
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
182
242
 
183
- uint8_t* destination_buffer = compressor_ptr->destination_buffer;
184
- size_t destination_buffer_length = compressor_ptr->destination_buffer_length;
185
- size_t remaining_destination_buffer_length = compressor_ptr->remaining_destination_buffer_length;
243
+ brs_ext_byte_t* destination_buffer = compressor_ptr->destination_buffer;
244
+ size_t destination_buffer_length = compressor_ptr->destination_buffer_length;
245
+ size_t remaining_destination_buffer_length = compressor_ptr->remaining_destination_buffer_length;
186
246
 
187
- const char* result = (const char*)destination_buffer;
247
+ const char* result = (const char*) destination_buffer;
188
248
  size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
189
-
190
- VALUE result_value = rb_str_new(result, result_length);
249
+ VALUE result_value = rb_str_new(result, result_length);
191
250
 
192
251
  compressor_ptr->remaining_destination_buffer = destination_buffer;
193
252
  compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
@@ -195,6 +254,8 @@ VALUE brs_ext_compressor_read_result(VALUE self)
195
254
  return result_value;
196
255
  }
197
256
 
257
+ // -- cleanup --
258
+
198
259
  VALUE brs_ext_compressor_close(VALUE self)
199
260
  {
200
261
  GET_COMPRESSOR(self);
@@ -207,7 +268,7 @@ VALUE brs_ext_compressor_close(VALUE self)
207
268
  compressor_ptr->state_ptr = NULL;
208
269
  }
209
270
 
210
- uint8_t* destination_buffer = compressor_ptr->destination_buffer;
271
+ brs_ext_byte_t* destination_buffer = compressor_ptr->destination_buffer;
211
272
  if (destination_buffer != NULL) {
212
273
  free(destination_buffer);
213
274
 
@@ -220,6 +281,8 @@ VALUE brs_ext_compressor_close(VALUE self)
220
281
  return Qnil;
221
282
  }
222
283
 
284
+ // -- exports --
285
+
223
286
  void brs_ext_compressor_exports(VALUE root_module)
224
287
  {
225
288
  VALUE module = rb_define_module_under(root_module, "Stream");