ruby-lzws 1.1.4 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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");
@@ -5,17 +5,20 @@
5
5
  #define LZWS_EXT_STREAM_COMPRESSOR_H
6
6
 
7
7
  #include <lzws/compressor/state.h>
8
+ #include <stdbool.h>
8
9
  #include <stdlib.h>
9
10
 
10
11
  #include "lzws_ext/common.h"
11
12
  #include "ruby.h"
12
13
 
13
- typedef struct {
14
+ typedef struct
15
+ {
14
16
  lzws_compressor_state_t* state_ptr;
15
17
  lzws_ext_byte_t* destination_buffer;
16
18
  size_t destination_buffer_length;
17
19
  lzws_ext_byte_t* remaining_destination_buffer;
18
20
  size_t remaining_destination_buffer_length;
21
+ bool gvl;
19
22
  } lzws_ext_compressor_t;
20
23
 
21
24
  VALUE lzws_ext_allocate_compressor(VALUE klass);
@@ -4,15 +4,16 @@
4
4
  #include "lzws_ext/stream/decompressor.h"
5
5
 
6
6
  #include <lzws/buffer.h>
7
- #include <lzws/common.h>
8
- #include <lzws/decompressor/common.h>
9
7
  #include <lzws/decompressor/main.h>
10
8
  #include <lzws/decompressor/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_decompressor(lzws_ext_decompressor_t* decompressor_ptr)
17
18
  {
18
19
  lzws_decompressor_state_t* state_ptr = decompressor_ptr->state_ptr;
@@ -31,7 +32,6 @@ static void free_decompressor(lzws_ext_decompressor_t* decompressor_ptr)
31
32
  VALUE lzws_ext_allocate_decompressor(VALUE klass)
32
33
  {
33
34
  lzws_ext_decompressor_t* decompressor_ptr;
34
-
35
35
  VALUE self = Data_Make_Struct(klass, lzws_ext_decompressor_t, NULL, free_decompressor, decompressor_ptr);
36
36
 
37
37
  decompressor_ptr->state_ptr = NULL;
@@ -51,15 +51,13 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
51
51
  {
52
52
  GET_DECOMPRESSOR(self);
53
53
  Check_Type(options, T_HASH);
54
+ LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
55
+ LZWS_EXT_GET_BOOL_OPTION(options, gvl);
54
56
  LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
55
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
56
57
 
57
58
  lzws_decompressor_state_t* state_ptr;
58
59
 
59
- lzws_result_t result = lzws_decompressor_get_initial_state(
60
- &state_ptr,
61
- without_magic_header, msb, unaligned_bit_groups, quiet);
62
-
60
+ lzws_result_t result = lzws_decompressor_get_initial_state(&state_ptr, &decompressor_options);
63
61
  if (result != 0) {
64
62
  switch (result) {
65
63
  case LZWS_DECOMPRESSOR_ALLOCATE_FAILED:
@@ -71,7 +69,9 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
71
69
 
72
70
  lzws_ext_byte_t* destination_buffer;
73
71
 
74
- result = lzws_create_destination_buffer_for_decompressor(&destination_buffer, &destination_buffer_length, quiet);
72
+ result = lzws_create_destination_buffer_for_decompressor(
73
+ &destination_buffer, &destination_buffer_length, decompressor_options.quiet);
74
+
75
75
  if (result != 0) {
76
76
  lzws_decompressor_free_state(state_ptr);
77
77
  lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
@@ -82,38 +82,60 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
82
82
  decompressor_ptr->destination_buffer_length = destination_buffer_length;
83
83
  decompressor_ptr->remaining_destination_buffer = destination_buffer;
84
84
  decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
85
+ decompressor_ptr->gvl = gvl;
85
86
 
86
87
  return Qnil;
87
88
  }
88
89
 
90
+ // -- decompress --
91
+
89
92
  #define DO_NOT_USE_AFTER_CLOSE(decompressor_ptr) \
90
93
  if (decompressor_ptr->state_ptr == NULL || decompressor_ptr->destination_buffer == NULL) { \
91
94
  lzws_ext_raise_error(LZWS_EXT_ERROR_USED_AFTER_CLOSE); \
92
95
  }
93
96
 
94
- #define GET_SOURCE_DATA(source_value) \
95
- Check_Type(source_value, T_STRING); \
96
- \
97
- const char* source = RSTRING_PTR(source_value); \
98
- size_t source_length = RSTRING_LEN(source_value); \
99
- lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*)source; \
100
- size_t remaining_source_length = source_length;
97
+ typedef struct
98
+ {
99
+ lzws_ext_decompressor_t* decompressor_ptr;
100
+ lzws_ext_byte_t* remaining_source;
101
+ size_t* remaining_source_length_ptr;
102
+ lzws_result_t result;
103
+ } decompress_args_t;
104
+
105
+ static inline void* decompress_wrapper(void* data)
106
+ {
107
+ decompress_args_t* args = data;
108
+ lzws_ext_decompressor_t* decompressor_ptr = args->decompressor_ptr;
109
+
110
+ args->result = lzws_decompress(
111
+ decompressor_ptr->state_ptr,
112
+ &args->remaining_source,
113
+ args->remaining_source_length_ptr,
114
+ &decompressor_ptr->remaining_destination_buffer,
115
+ &decompressor_ptr->remaining_destination_buffer_length);
116
+
117
+ return NULL;
118
+ }
101
119
 
102
120
  VALUE lzws_ext_decompress(VALUE self, VALUE source_value)
103
121
  {
104
122
  GET_DECOMPRESSOR(self);
105
123
  DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
106
- GET_SOURCE_DATA(source_value);
124
+ Check_Type(source_value, T_STRING);
107
125
 
108
- lzws_result_t result = lzws_decompress(
109
- decompressor_ptr->state_ptr,
110
- &remaining_source, &remaining_source_length,
111
- &decompressor_ptr->remaining_destination_buffer, &decompressor_ptr->remaining_destination_buffer_length);
126
+ const char* source = RSTRING_PTR(source_value);
127
+ size_t source_length = RSTRING_LEN(source_value);
128
+ lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*) source;
129
+ size_t remaining_source_length = source_length;
112
130
 
113
- if (
114
- result != 0 &&
115
- result != LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
116
- switch (result) {
131
+ decompress_args_t args = {
132
+ .decompressor_ptr = decompressor_ptr,
133
+ .remaining_source = remaining_source,
134
+ .remaining_source_length_ptr = &remaining_source_length};
135
+
136
+ LZWS_EXT_GVL_WRAP(decompressor_ptr->gvl, decompress_wrapper, &args);
137
+ if (args.result != 0 && args.result != LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
138
+ switch (args.result) {
117
139
  case LZWS_DECOMPRESSOR_INVALID_MAGIC_HEADER:
118
140
  case LZWS_DECOMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH:
119
141
  lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
@@ -125,11 +147,13 @@ VALUE lzws_ext_decompress(VALUE self, VALUE source_value)
125
147
  }
126
148
 
127
149
  VALUE bytes_read = SIZET2NUM(source_length - remaining_source_length);
128
- VALUE needs_more_destination = result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
150
+ VALUE needs_more_destination = args.result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
129
151
 
130
152
  return rb_ary_new_from_args(2, bytes_read, needs_more_destination);
131
153
  }
132
154
 
155
+ // -- other --
156
+
133
157
  VALUE lzws_ext_decompressor_read_result(VALUE self)
134
158
  {
135
159
  GET_DECOMPRESSOR(self);
@@ -139,10 +163,9 @@ VALUE lzws_ext_decompressor_read_result(VALUE self)
139
163
  size_t destination_buffer_length = decompressor_ptr->destination_buffer_length;
140
164
  size_t remaining_destination_buffer_length = decompressor_ptr->remaining_destination_buffer_length;
141
165
 
142
- const char* result = (const char*)destination_buffer;
166
+ const char* result = (const char*) destination_buffer;
143
167
  size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
144
-
145
- VALUE result_value = rb_str_new(result, result_length);
168
+ VALUE result_value = rb_str_new(result, result_length);
146
169
 
147
170
  decompressor_ptr->remaining_destination_buffer = destination_buffer;
148
171
  decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
@@ -150,6 +173,8 @@ VALUE lzws_ext_decompressor_read_result(VALUE self)
150
173
  return result_value;
151
174
  }
152
175
 
176
+ // -- cleanup --
177
+
153
178
  VALUE lzws_ext_decompressor_close(VALUE self)
154
179
  {
155
180
  GET_DECOMPRESSOR(self);
@@ -175,6 +200,8 @@ VALUE lzws_ext_decompressor_close(VALUE self)
175
200
  return Qnil;
176
201
  }
177
202
 
203
+ // -- exports --
204
+
178
205
  void lzws_ext_decompressor_exports(VALUE root_module)
179
206
  {
180
207
  VALUE module = rb_define_module_under(root_module, "Stream");