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