ruby-brs 1.1.4 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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);