ruby-lzws 1.1.5 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/lzws_ext/io.c CHANGED
@@ -1,16 +1,18 @@
1
1
  // Ruby bindings for lzws library.
2
2
  // Copyright (c) 2019 AUTHORS, MIT License.
3
3
 
4
- #include "ruby/io.h"
4
+ #include "lzws_ext/io.h"
5
5
 
6
- #include <lzws/common.h>
7
6
  #include <lzws/file.h>
8
7
 
9
8
  #include "lzws_ext/error.h"
10
- #include "lzws_ext/io.h"
9
+ #include "lzws_ext/gvl.h"
11
10
  #include "lzws_ext/macro.h"
12
11
  #include "lzws_ext/option.h"
13
12
  #include "ruby.h"
13
+ #include "ruby/io.h"
14
+
15
+ // -- utils --
14
16
 
15
17
  #define GET_FILE(target) \
16
18
  Check_Type(target, T_FILE); \
@@ -48,22 +50,52 @@ static inline lzws_ext_result_t get_file_error(lzws_result_t result)
48
50
  }
49
51
  }
50
52
 
53
+ // -- compress --
54
+
55
+ typedef struct
56
+ {
57
+ FILE* source_file;
58
+ size_t source_buffer_length;
59
+ FILE* destination_file;
60
+ size_t destination_buffer_length;
61
+ lzws_compressor_options_t* compressor_options_ptr;
62
+ lzws_result_t result;
63
+ } compress_args_t;
64
+
65
+ static inline void* compress_wrapper(void* data)
66
+ {
67
+ compress_args_t* args = data;
68
+
69
+ args->result = lzws_compress_file(
70
+ args->source_file,
71
+ args->source_buffer_length,
72
+ args->destination_file,
73
+ args->destination_buffer_length,
74
+ args->compressor_options_ptr);
75
+
76
+ return NULL;
77
+ }
78
+
51
79
  VALUE lzws_ext_compress_io(VALUE LZWS_EXT_UNUSED(self), VALUE source, VALUE destination, VALUE options)
52
80
  {
53
81
  GET_FILE(source);
54
82
  GET_FILE(destination);
55
83
  Check_Type(options, T_HASH);
84
+ LZWS_EXT_GET_SIZE_OPTION(options, source_buffer_length);
85
+ LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
86
+ LZWS_EXT_GET_BOOL_OPTION(options, gvl);
56
87
  LZWS_EXT_GET_COMPRESSOR_OPTIONS(options);
57
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, source_buffer_length);
58
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
59
88
 
60
- lzws_result_t result = lzws_compress_file(
61
- source_file, source_buffer_length,
62
- destination_file, destination_buffer_length,
63
- without_magic_header, max_code_bit_length, block_mode, msb, unaligned_bit_groups, quiet);
89
+ compress_args_t args = {
90
+ .source_file = source_file,
91
+ .source_buffer_length = source_buffer_length,
92
+ .destination_file = destination_file,
93
+ .destination_buffer_length = destination_buffer_length,
94
+ .compressor_options_ptr = &compressor_options};
64
95
 
65
- if (result != 0) {
66
- lzws_ext_raise_error(get_file_error(result));
96
+ LZWS_EXT_GVL_WRAP(gvl, compress_wrapper, &args);
97
+ if (args.result != 0) {
98
+ lzws_ext_raise_error(get_file_error(args.result));
67
99
  }
68
100
 
69
101
  // Ruby itself won't flush stdio file before closing fd, flush is required.
@@ -72,22 +104,52 @@ VALUE lzws_ext_compress_io(VALUE LZWS_EXT_UNUSED(self), VALUE source, VALUE dest
72
104
  return Qnil;
73
105
  }
74
106
 
107
+ // -- decompress --
108
+
109
+ typedef struct
110
+ {
111
+ FILE* source_file;
112
+ size_t source_buffer_length;
113
+ FILE* destination_file;
114
+ size_t destination_buffer_length;
115
+ lzws_decompressor_options_t* decompressor_options_ptr;
116
+ lzws_result_t result;
117
+ } decompress_args_t;
118
+
119
+ static inline void* decompress_wrapper(void* data)
120
+ {
121
+ decompress_args_t* args = data;
122
+
123
+ args->result = lzws_decompress_file(
124
+ args->source_file,
125
+ args->source_buffer_length,
126
+ args->destination_file,
127
+ args->destination_buffer_length,
128
+ args->decompressor_options_ptr);
129
+
130
+ return NULL;
131
+ }
132
+
75
133
  VALUE lzws_ext_decompress_io(VALUE LZWS_EXT_UNUSED(self), VALUE source, VALUE destination, VALUE options)
76
134
  {
77
135
  GET_FILE(source);
78
136
  GET_FILE(destination);
79
137
  Check_Type(options, T_HASH);
138
+ LZWS_EXT_GET_SIZE_OPTION(options, source_buffer_length);
139
+ LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
140
+ LZWS_EXT_GET_BOOL_OPTION(options, gvl);
80
141
  LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
81
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, source_buffer_length);
82
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
83
142
 
84
- lzws_result_t result = lzws_decompress_file(
85
- source_file, source_buffer_length,
86
- destination_file, destination_buffer_length,
87
- without_magic_header, msb, unaligned_bit_groups, quiet);
143
+ decompress_args_t args = {
144
+ .source_file = source_file,
145
+ .source_buffer_length = source_buffer_length,
146
+ .destination_file = destination_file,
147
+ .destination_buffer_length = destination_buffer_length,
148
+ .decompressor_options_ptr = &decompressor_options};
88
149
 
89
- if (result != 0) {
90
- lzws_ext_raise_error(get_file_error(result));
150
+ LZWS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
151
+ if (args.result != 0) {
152
+ lzws_ext_raise_error(get_file_error(args.result));
91
153
  }
92
154
 
93
155
  // Ruby itself won't flush stdio file before closing fd, flush is required.
@@ -96,6 +158,8 @@ VALUE lzws_ext_decompress_io(VALUE LZWS_EXT_UNUSED(self), VALUE source, VALUE de
96
158
  return Qnil;
97
159
  }
98
160
 
161
+ // -- exports --
162
+
99
163
  void lzws_ext_io_exports(VALUE root_module)
100
164
  {
101
165
  rb_define_module_function(root_module, "_native_compress_io", RUBY_METHOD_FUNC(lzws_ext_compress_io), 3);
data/ext/lzws_ext/main.c CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "lzws_ext/buffer.h"
5
5
  #include "lzws_ext/io.h"
6
+ #include "lzws_ext/option.h"
6
7
  #include "lzws_ext/stream/compressor.h"
7
8
  #include "lzws_ext/stream/decompressor.h"
8
9
  #include "lzws_ext/string.h"
@@ -14,6 +15,7 @@ void Init_lzws_ext()
14
15
 
15
16
  lzws_ext_buffer_exports(root_module);
16
17
  lzws_ext_io_exports(root_module);
18
+ lzws_ext_option_exports(root_module);
17
19
  lzws_ext_compressor_exports(root_module);
18
20
  lzws_ext_decompressor_exports(root_module);
19
21
  lzws_ext_string_exports(root_module);
@@ -6,15 +6,15 @@
6
6
  #include "lzws_ext/error.h"
7
7
  #include "ruby.h"
8
8
 
9
- static inline VALUE get_raw_option_value(VALUE options, const char* name)
9
+ // -- values --
10
+
11
+ static inline VALUE get_raw_value(VALUE options, const char* name)
10
12
  {
11
13
  return rb_funcall(options, rb_intern("[]"), 1, ID2SYM(rb_intern(name)));
12
14
  }
13
15
 
14
- bool lzws_ext_get_bool_option_value(VALUE options, const char* name)
16
+ static inline bool get_bool_value(VALUE raw_value)
15
17
  {
16
- VALUE raw_value = get_raw_option_value(options, name);
17
-
18
18
  int raw_type = TYPE(raw_value);
19
19
  if (raw_type != T_TRUE && raw_type != T_FALSE) {
20
20
  lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
@@ -23,20 +23,56 @@ bool lzws_ext_get_bool_option_value(VALUE options, const char* name)
23
23
  return raw_type == T_TRUE;
24
24
  }
25
25
 
26
- unsigned int lzws_ext_get_uint_option_value(VALUE options, const char* name)
26
+ static inline unsigned int get_uint_value(VALUE raw_value)
27
27
  {
28
- VALUE raw_value = get_raw_option_value(options, name);
29
-
30
28
  Check_Type(raw_value, T_FIXNUM);
31
29
 
32
30
  return NUM2UINT(raw_value);
33
31
  }
34
32
 
35
- size_t lzws_ext_get_size_option_value(VALUE options, const char* name)
33
+ static inline size_t get_size_value(VALUE raw_value)
36
34
  {
37
- VALUE raw_value = get_raw_option_value(options, name);
38
-
39
35
  Check_Type(raw_value, T_FIXNUM);
40
36
 
41
37
  return NUM2SIZET(raw_value);
42
38
  }
39
+
40
+ void lzws_ext_resolve_bool_option(VALUE options, bool* option, const char* name)
41
+ {
42
+ VALUE raw_value = get_raw_value(options, name);
43
+ if (raw_value != Qnil) {
44
+ *option = get_bool_value(raw_value);
45
+ }
46
+ }
47
+
48
+ void lzws_ext_resolve_max_code_bit_length_option(VALUE options, lzws_byte_fast_t* option, const char* name)
49
+ {
50
+ VALUE raw_value = get_raw_value(options, name);
51
+ if (raw_value != Qnil) {
52
+ *option = get_uint_value(raw_value);
53
+ }
54
+ }
55
+
56
+ bool lzws_ext_get_bool_option_value(VALUE options, const char* name)
57
+ {
58
+ VALUE raw_value = get_raw_value(options, name);
59
+
60
+ return get_bool_value(raw_value);
61
+ }
62
+
63
+ size_t lzws_ext_get_size_option_value(VALUE options, const char* name)
64
+ {
65
+ VALUE raw_value = get_raw_value(options, name);
66
+
67
+ return get_size_value(raw_value);
68
+ }
69
+
70
+ // -- exports --
71
+
72
+ void lzws_ext_option_exports(VALUE root_module)
73
+ {
74
+ VALUE module = rb_define_module_under(root_module, "Option");
75
+
76
+ rb_define_const(module, "LOWEST_MAX_CODE_BIT_LENGTH", UINT2NUM(LZWS_LOWEST_MAX_CODE_BIT_LENGTH));
77
+ rb_define_const(module, "BIGGEST_MAX_CODE_BIT_LENGTH", UINT2NUM(LZWS_BIGGEST_MAX_CODE_BIT_LENGTH));
78
+ }
@@ -4,40 +4,46 @@
4
4
  #if !defined(LZWS_EXT_OPTIONS_H)
5
5
  #define LZWS_EXT_OPTIONS_H
6
6
 
7
+ #include <lzws/compressor/common.h>
8
+ #include <lzws/decompressor/common.h>
7
9
  #include <stdbool.h>
8
10
  #include <stdlib.h>
9
11
 
10
- #include "lzws_ext/common.h"
11
12
  #include "ruby.h"
12
13
 
13
- bool lzws_ext_get_bool_option_value(VALUE options, const char* name);
14
- unsigned int lzws_ext_get_uint_option_value(VALUE options, const char* name);
15
- size_t lzws_ext_get_size_option_value(VALUE options, const char* name);
14
+ void lzws_ext_resolve_bool_option(VALUE options, bool* option, const char* name);
15
+ void lzws_ext_resolve_max_code_bit_length_option(VALUE options, lzws_byte_fast_t* option, const char* name);
16
16
 
17
- #define LZWS_EXT_GET_BOOL_OPTION(options, name) \
18
- bool name = lzws_ext_get_bool_option_value(options, #name);
17
+ #define LZWS_EXT_RESOLVE_BOOL_OPTION(options, target_options, name) \
18
+ lzws_ext_resolve_bool_option(options, &target_options.name, #name);
19
19
 
20
- #define LZWS_EXT_GET_UINT_OPTION(options, type, name) \
21
- type name = lzws_ext_get_uint_option_value(options, #name);
20
+ #define LZWS_EXT_RESOLVE_MAX_CODE_BIT_LENGTH_OPTION(options, target_options, name) \
21
+ lzws_ext_resolve_max_code_bit_length_option(options, &target_options.name, #name);
22
22
 
23
- #define LZWS_EXT_GET_SIZE_OPTION(options, name) \
24
- size_t name = lzws_ext_get_size_option_value(options, #name);
23
+ #define LZWS_EXT_GET_COMPRESSOR_OPTIONS(options) \
24
+ lzws_compressor_options_t compressor_options = LZWS_COMPRESSOR_DEFAULT_OPTIONS; \
25
+ \
26
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, compressor_options, without_magic_header); \
27
+ LZWS_EXT_RESOLVE_MAX_CODE_BIT_LENGTH_OPTION(options, compressor_options, max_code_bit_length); \
28
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, compressor_options, block_mode); \
29
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, compressor_options, msb); \
30
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, compressor_options, unaligned_bit_groups); \
31
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, compressor_options, quiet);
25
32
 
26
- #define LZWS_EXT_GET_COMPRESSOR_OPTIONS(options) \
27
- LZWS_EXT_GET_BOOL_OPTION(options, without_magic_header); \
28
- LZWS_EXT_GET_UINT_OPTION(options, lzws_ext_byte_fast_t, max_code_bit_length); \
29
- LZWS_EXT_GET_BOOL_OPTION(options, block_mode); \
30
- LZWS_EXT_GET_BOOL_OPTION(options, msb); \
31
- LZWS_EXT_GET_BOOL_OPTION(options, unaligned_bit_groups); \
32
- LZWS_EXT_GET_BOOL_OPTION(options, quiet);
33
+ #define LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options) \
34
+ lzws_decompressor_options_t decompressor_options = LZWS_DECOMPRESSOR_DEFAULT_OPTIONS; \
35
+ \
36
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, decompressor_options, without_magic_header); \
37
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, decompressor_options, msb); \
38
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, decompressor_options, unaligned_bit_groups); \
39
+ LZWS_EXT_RESOLVE_BOOL_OPTION(options, decompressor_options, quiet);
33
40
 
34
- #define LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options) \
35
- LZWS_EXT_GET_BOOL_OPTION(options, without_magic_header); \
36
- LZWS_EXT_GET_BOOL_OPTION(options, msb); \
37
- LZWS_EXT_GET_BOOL_OPTION(options, unaligned_bit_groups); \
38
- LZWS_EXT_GET_BOOL_OPTION(options, quiet);
41
+ bool lzws_ext_get_bool_option_value(VALUE options, const char* name);
42
+ size_t lzws_ext_get_size_option_value(VALUE options, const char* name);
39
43
 
40
- #define LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, name) \
41
- LZWS_EXT_GET_SIZE_OPTION(options, name);
44
+ #define LZWS_EXT_GET_BOOL_OPTION(options, name) bool name = lzws_ext_get_bool_option_value(options, #name);
45
+ #define LZWS_EXT_GET_SIZE_OPTION(options, name) size_t name = lzws_ext_get_size_option_value(options, #name);
46
+
47
+ void lzws_ext_option_exports(VALUE root_module);
42
48
 
43
49
  #endif // LZWS_EXT_OPTIONS_H
@@ -4,15 +4,16 @@
4
4
  #include "lzws_ext/stream/compressor.h"
5
5
 
6
6
  #include <lzws/buffer.h>
7
- #include <lzws/common.h>
8
- #include <lzws/compressor/common.h>
9
7
  #include <lzws/compressor/main.h>
10
8
  #include <lzws/compressor/state.h>
11
9
 
12
10
  #include "lzws_ext/error.h"
11
+ #include "lzws_ext/gvl.h"
13
12
  #include "lzws_ext/option.h"
14
13
  #include "ruby.h"
15
14
 
15
+ // -- initialization --
16
+
16
17
  static void free_compressor(lzws_ext_compressor_t* compressor_ptr)
17
18
  {
18
19
  lzws_compressor_state_t* state_ptr = compressor_ptr->state_ptr;
@@ -31,14 +32,14 @@ static void free_compressor(lzws_ext_compressor_t* compressor_ptr)
31
32
  VALUE lzws_ext_allocate_compressor(VALUE klass)
32
33
  {
33
34
  lzws_ext_compressor_t* compressor_ptr;
34
-
35
- VALUE self = Data_Make_Struct(klass, lzws_ext_compressor_t, NULL, free_compressor, compressor_ptr);
35
+ VALUE self = Data_Make_Struct(klass, lzws_ext_compressor_t, NULL, free_compressor, compressor_ptr);
36
36
 
37
37
  compressor_ptr->state_ptr = NULL;
38
38
  compressor_ptr->destination_buffer = NULL;
39
39
  compressor_ptr->destination_buffer_length = 0;
40
40
  compressor_ptr->remaining_destination_buffer = NULL;
41
41
  compressor_ptr->remaining_destination_buffer_length = 0;
42
+ compressor_ptr->gvl = false;
42
43
 
43
44
  return self;
44
45
  }
@@ -51,15 +52,13 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
51
52
  {
52
53
  GET_COMPRESSOR(self);
53
54
  Check_Type(options, T_HASH);
55
+ LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
56
+ LZWS_EXT_GET_BOOL_OPTION(options, gvl);
54
57
  LZWS_EXT_GET_COMPRESSOR_OPTIONS(options);
55
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
56
58
 
57
59
  lzws_compressor_state_t* state_ptr;
58
60
 
59
- lzws_result_t result = lzws_compressor_get_initial_state(
60
- &state_ptr,
61
- without_magic_header, max_code_bit_length, block_mode, msb, unaligned_bit_groups, quiet);
62
-
61
+ lzws_result_t result = lzws_compressor_get_initial_state(&state_ptr, &compressor_options);
63
62
  if (result != 0) {
64
63
  switch (result) {
65
64
  case LZWS_COMPRESSOR_ALLOCATE_FAILED:
@@ -73,7 +72,9 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
73
72
 
74
73
  lzws_ext_byte_t* destination_buffer;
75
74
 
76
- result = lzws_create_destination_buffer_for_compressor(&destination_buffer, &destination_buffer_length, quiet);
75
+ result = lzws_create_destination_buffer_for_compressor(
76
+ &destination_buffer, &destination_buffer_length, compressor_options.quiet);
77
+
77
78
  if (result != 0) {
78
79
  lzws_compressor_free_state(state_ptr);
79
80
  lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
@@ -84,66 +85,106 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
84
85
  compressor_ptr->destination_buffer_length = destination_buffer_length;
85
86
  compressor_ptr->remaining_destination_buffer = destination_buffer;
86
87
  compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
88
+ compressor_ptr->gvl = gvl;
87
89
 
88
90
  return Qnil;
89
91
  }
90
92
 
93
+ // -- compress --
94
+
91
95
  #define DO_NOT_USE_AFTER_CLOSE(compressor_ptr) \
92
96
  if (compressor_ptr->state_ptr == NULL || compressor_ptr->destination_buffer == NULL) { \
93
97
  lzws_ext_raise_error(LZWS_EXT_ERROR_USED_AFTER_CLOSE); \
94
98
  }
95
99
 
96
- #define GET_SOURCE_DATA(source_value) \
97
- Check_Type(source_value, T_STRING); \
98
- \
99
- const char* source = RSTRING_PTR(source_value); \
100
- size_t source_length = RSTRING_LEN(source_value); \
101
- lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*)source; \
102
- size_t remaining_source_length = source_length;
100
+ typedef struct
101
+ {
102
+ lzws_ext_compressor_t* compressor_ptr;
103
+ lzws_ext_byte_t* remaining_source;
104
+ size_t* remaining_source_length_ptr;
105
+ lzws_result_t result;
106
+ } compress_args_t;
107
+
108
+ static inline void* compress_wrapper(void* data)
109
+ {
110
+ compress_args_t* args = data;
111
+ lzws_ext_compressor_t* compressor_ptr = args->compressor_ptr;
112
+
113
+ args->result = lzws_compress(
114
+ compressor_ptr->state_ptr,
115
+ &args->remaining_source,
116
+ args->remaining_source_length_ptr,
117
+ &compressor_ptr->remaining_destination_buffer,
118
+ &compressor_ptr->remaining_destination_buffer_length);
119
+
120
+ return NULL;
121
+ }
103
122
 
104
123
  VALUE lzws_ext_compress(VALUE self, VALUE source_value)
105
124
  {
106
125
  GET_COMPRESSOR(self);
107
126
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
108
- GET_SOURCE_DATA(source_value);
127
+ Check_Type(source_value, T_STRING);
109
128
 
110
- lzws_result_t result = lzws_compress(
111
- compressor_ptr->state_ptr,
112
- &remaining_source, &remaining_source_length,
113
- &compressor_ptr->remaining_destination_buffer, &compressor_ptr->remaining_destination_buffer_length);
129
+ const char* source = RSTRING_PTR(source_value);
130
+ size_t source_length = RSTRING_LEN(source_value);
131
+ lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*) source;
132
+ size_t remaining_source_length = source_length;
133
+
134
+ compress_args_t args = {
135
+ .compressor_ptr = compressor_ptr,
136
+ .remaining_source = remaining_source,
137
+ .remaining_source_length_ptr = &remaining_source_length};
114
138
 
115
- if (
116
- result != 0 &&
117
- result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
139
+ LZWS_EXT_GVL_WRAP(compressor_ptr->gvl, compress_wrapper, &args);
140
+ if (args.result != 0 && args.result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
118
141
  lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
119
142
  }
120
143
 
121
144
  VALUE bytes_written = SIZET2NUM(source_length - remaining_source_length);
122
- VALUE needs_more_destination = result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
145
+ VALUE needs_more_destination = args.result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
123
146
 
124
147
  return rb_ary_new_from_args(2, bytes_written, needs_more_destination);
125
148
  }
126
149
 
150
+ // -- compressor finish --
151
+
152
+ typedef struct
153
+ {
154
+ lzws_ext_compressor_t* compressor_ptr;
155
+ lzws_result_t result;
156
+ } compressor_finish_args_t;
157
+
158
+ static inline void* compressor_finish_wrapper(void* data)
159
+ {
160
+ compressor_finish_args_t* args = data;
161
+ lzws_ext_compressor_t* compressor_ptr = args->compressor_ptr;
162
+
163
+ args->result = lzws_compressor_finish(
164
+ compressor_ptr->state_ptr,
165
+ &compressor_ptr->remaining_destination_buffer,
166
+ &compressor_ptr->remaining_destination_buffer_length);
167
+
168
+ return NULL;
169
+ }
170
+
127
171
  VALUE lzws_ext_compressor_finish(VALUE self)
128
172
  {
129
173
  GET_COMPRESSOR(self);
130
174
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
131
175
 
132
- lzws_result_t result = lzws_compressor_finish(
133
- compressor_ptr->state_ptr,
134
- &compressor_ptr->remaining_destination_buffer, &compressor_ptr->remaining_destination_buffer_length);
176
+ compressor_finish_args_t args = {.compressor_ptr = compressor_ptr};
135
177
 
136
- if (
137
- result != 0 &&
138
- result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
178
+ LZWS_EXT_GVL_WRAP(compressor_ptr->gvl, compressor_finish_wrapper, &args);
179
+ if (args.result != 0 && args.result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
139
180
  lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
140
181
  }
141
182
 
142
- VALUE needs_more_destination = result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
143
-
144
- return needs_more_destination;
183
+ return args.result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
145
184
  }
146
185
 
186
+ // -- other --
187
+
147
188
  VALUE lzws_ext_compressor_read_result(VALUE self)
148
189
  {
149
190
  GET_COMPRESSOR(self);
@@ -153,10 +194,9 @@ VALUE lzws_ext_compressor_read_result(VALUE self)
153
194
  size_t destination_buffer_length = compressor_ptr->destination_buffer_length;
154
195
  size_t remaining_destination_buffer_length = compressor_ptr->remaining_destination_buffer_length;
155
196
 
156
- const char* result = (const char*)destination_buffer;
197
+ const char* result = (const char*) destination_buffer;
157
198
  size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
158
-
159
- VALUE result_value = rb_str_new(result, result_length);
199
+ VALUE result_value = rb_str_new(result, result_length);
160
200
 
161
201
  compressor_ptr->remaining_destination_buffer = destination_buffer;
162
202
  compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
@@ -164,6 +204,8 @@ VALUE lzws_ext_compressor_read_result(VALUE self)
164
204
  return result_value;
165
205
  }
166
206
 
207
+ // -- cleanup --
208
+
167
209
  VALUE lzws_ext_compressor_close(VALUE self)
168
210
  {
169
211
  GET_COMPRESSOR(self);
@@ -183,12 +225,14 @@ VALUE lzws_ext_compressor_close(VALUE self)
183
225
  compressor_ptr->destination_buffer = NULL;
184
226
  }
185
227
 
186
- // It is possible to keep "destination_buffer_length", "remaining_destination_buffer"
187
- // and "remaining_destination_buffer_length" as is.
228
+ // It is possible to keep "destination_buffer_length", "remaining_destination_buffer",
229
+ // "remaining_destination_buffer_length" and "gvl" as is.
188
230
 
189
231
  return Qnil;
190
232
  }
191
233
 
234
+ // -- exports --
235
+
192
236
  void lzws_ext_compressor_exports(VALUE root_module)
193
237
  {
194
238
  VALUE module = rb_define_module_under(root_module, "Stream");