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.
- checksums.yaml +4 -4
- data/README.md +86 -46
- data/ext/brs_ext/buffer.c +21 -9
- data/ext/brs_ext/buffer.h +7 -7
- data/ext/brs_ext/error.c +11 -15
- data/ext/brs_ext/error.h +2 -1
- data/ext/brs_ext/gvl.h +24 -0
- data/ext/brs_ext/io.c +240 -123
- data/ext/brs_ext/main.c +4 -1
- data/ext/brs_ext/option.c +54 -33
- data/ext/brs_ext/option.h +41 -29
- data/ext/brs_ext/stream/compressor.c +118 -54
- data/ext/brs_ext/stream/compressor.h +4 -1
- data/ext/brs_ext/stream/decompressor.c +54 -25
- data/ext/brs_ext/stream/decompressor.h +4 -1
- data/ext/brs_ext/string.c +118 -65
- data/ext/extconf.rb +90 -10
- data/lib/brs/file.rb +2 -2
- data/lib/brs/option.rb +36 -4
- data/lib/brs/stream/abstract.rb +5 -3
- data/lib/brs/stream/reader.rb +3 -2
- data/lib/brs/stream/reader_helpers.rb +1 -1
- data/lib/brs/validation.rb +3 -1
- data/lib/brs/version.rb +1 -1
- metadata +74 -17
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
|
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
|
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
|
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
|
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
|
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 =
|
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 =
|
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)
|
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)
|
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
|
-
|
83
|
+
bool brs_ext_get_bool_option_value(VALUE options, const char* name)
|
84
84
|
{
|
85
|
-
VALUE raw_value =
|
85
|
+
VALUE raw_value = get_raw_value(options, name);
|
86
86
|
|
87
|
-
|
87
|
+
return get_bool_value(raw_value);
|
88
|
+
}
|
88
89
|
|
89
|
-
|
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,
|
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(
|
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(
|
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 =
|
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
|
48
|
-
|
49
|
-
#define
|
50
|
-
|
51
|
-
|
52
|
-
#define BRS_EXT_GET_COMPRESSOR_OPTIONS(options)
|
53
|
-
brs_ext_compressor_options_t compressor_options;
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
72
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
91
|
-
|
92
|
-
|
93
|
-
const
|
94
|
-
size_t
|
95
|
-
|
96
|
-
|
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
|
-
|
124
|
+
Check_Type(source_value, T_STRING);
|
103
125
|
|
104
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
&remaining_source_length
|
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
|
-
|
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
|
-
|
124
|
-
{
|
125
|
-
GET_COMPRESSOR(self);
|
126
|
-
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
147
|
+
// -- compressor flush --
|
127
148
|
|
128
|
-
|
149
|
+
typedef struct
|
150
|
+
{
|
151
|
+
brs_ext_compressor_t* compressor_ptr;
|
152
|
+
BROTLI_BOOL result;
|
153
|
+
} compressor_flush_args_t;
|
129
154
|
|
130
|
-
|
131
|
-
|
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
|
-
|
134
|
-
state_ptr,
|
162
|
+
args->result = BrotliEncoderCompressStream(
|
163
|
+
compressor_ptr->state_ptr,
|
135
164
|
BROTLI_OPERATION_FLUSH,
|
136
|
-
&remaining_source_length,
|
137
|
-
&
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
221
|
+
compressor_finish_args_t args = {.compressor_ptr = compressor_ptr};
|
155
222
|
|
156
|
-
|
157
|
-
|
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
|
-
|
171
|
-
|
172
|
-
|
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);
|