ruby-lzws 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.
@@ -5,17 +5,20 @@
5
5
  #define LZWS_EXT_STREAM_DECOMPRESSOR_H
6
6
 
7
7
  #include <lzws/decompressor/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_decompressor_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_decompressor_t;
20
23
 
21
24
  VALUE lzws_ext_allocate_decompressor(VALUE klass);
@@ -4,17 +4,15 @@
4
4
  #include "lzws_ext/string.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
- #include <lzws/decompressor/common.h>
12
9
  #include <lzws/decompressor/main.h>
13
10
  #include <lzws/decompressor/state.h>
14
11
  #include <stdlib.h>
15
12
 
16
13
  #include "lzws_ext/buffer.h"
17
14
  #include "lzws_ext/error.h"
15
+ #include "lzws_ext/gvl.h"
18
16
  #include "lzws_ext/macro.h"
19
17
  #include "lzws_ext/option.h"
20
18
  #include "ruby.h"
@@ -22,8 +20,10 @@
22
20
  // -- buffer --
23
21
 
24
22
  static inline lzws_ext_result_t increase_destination_buffer(
25
- VALUE destination_value, size_t destination_length,
26
- size_t* remaining_destination_buffer_length_ptr, size_t destination_buffer_length)
23
+ VALUE destination_value,
24
+ size_t destination_length,
25
+ size_t* remaining_destination_buffer_length_ptr,
26
+ size_t destination_buffer_length)
27
27
  {
28
28
  if (*remaining_destination_buffer_length_ptr == destination_buffer_length) {
29
29
  // We want to write more data at once, than buffer has.
@@ -42,62 +42,103 @@ static inline lzws_ext_result_t increase_destination_buffer(
42
42
  return 0;
43
43
  }
44
44
 
45
- // -- utils --
45
+ // -- compress --
46
46
 
47
- #define GET_SOURCE_DATA(source_value) \
48
- Check_Type(source_value, T_STRING); \
49
- \
50
- const char* source = RSTRING_PTR(source_value); \
51
- size_t source_length = RSTRING_LEN(source_value);
47
+ typedef struct
48
+ {
49
+ lzws_compressor_state_t* state_ptr;
50
+ lzws_ext_byte_t** remaining_source_ptr;
51
+ size_t* remaining_source_length_ptr;
52
+ lzws_ext_byte_t* remaining_destination_buffer;
53
+ size_t* remaining_destination_buffer_length_ptr;
54
+ lzws_result_t result;
55
+ } compress_args_t;
56
+
57
+ typedef struct
58
+ {
59
+ lzws_compressor_state_t* state_ptr;
60
+ lzws_ext_byte_t* remaining_destination_buffer;
61
+ size_t* remaining_destination_buffer_length_ptr;
62
+ lzws_result_t result;
63
+ } compressor_finish_args_t;
52
64
 
53
- // -- compress --
65
+ static inline void* compress_wrapper(void* data)
66
+ {
67
+ compress_args_t* args = data;
68
+
69
+ args->result = lzws_compress(
70
+ args->state_ptr,
71
+ args->remaining_source_ptr,
72
+ args->remaining_source_length_ptr,
73
+ &args->remaining_destination_buffer,
74
+ args->remaining_destination_buffer_length_ptr);
54
75
 
55
- #define BUFFERED_COMPRESS(function, ...) \
56
- while (true) { \
57
- lzws_ext_byte_t* remaining_destination_buffer = (lzws_ext_byte_t*)RSTRING_PTR(destination_value) + destination_length; \
58
- size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length; \
59
- \
60
- result = function(__VA_ARGS__, &remaining_destination_buffer, &remaining_destination_buffer_length); \
61
- \
62
- if ( \
63
- result != 0 && \
64
- result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) { \
65
- return LZWS_EXT_ERROR_UNEXPECTED; \
66
- } \
67
- \
68
- destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length; \
69
- \
70
- if (result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) { \
71
- ext_result = increase_destination_buffer( \
72
- destination_value, destination_length, \
73
- &remaining_destination_buffer_length, destination_buffer_length); \
74
- \
75
- if (ext_result != 0) { \
76
- return ext_result; \
77
- } \
78
- \
79
- continue; \
80
- } \
81
- \
82
- break; \
76
+ return NULL;
77
+ }
78
+
79
+ static inline void* compressor_finish_wrapper(void* data)
80
+ {
81
+ compressor_finish_args_t* args = data;
82
+
83
+ args->result = lzws_compressor_finish(
84
+ args->state_ptr, &args->remaining_destination_buffer, args->remaining_destination_buffer_length_ptr);
85
+
86
+ return NULL;
87
+ }
88
+
89
+ #define BUFFERED_COMPRESS(gvl, wrapper, args) \
90
+ while (true) { \
91
+ lzws_ext_byte_t* remaining_destination_buffer = \
92
+ (lzws_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length; \
93
+ size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length; \
94
+ \
95
+ args.remaining_destination_buffer = remaining_destination_buffer; \
96
+ args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length; \
97
+ \
98
+ LZWS_EXT_GVL_WRAP(gvl, wrapper, &args); \
99
+ if (args.result != 0 && args.result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) { \
100
+ return LZWS_EXT_ERROR_UNEXPECTED; \
101
+ } \
102
+ \
103
+ destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length; \
104
+ \
105
+ if (args.result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) { \
106
+ ext_result = increase_destination_buffer( \
107
+ destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length); \
108
+ \
109
+ if (ext_result != 0) { \
110
+ return ext_result; \
111
+ } \
112
+ \
113
+ continue; \
114
+ } \
115
+ \
116
+ break; \
83
117
  }
84
118
 
85
119
  static inline lzws_ext_result_t compress(
86
120
  lzws_compressor_state_t* state_ptr,
87
- const char* source, size_t source_length,
88
- VALUE destination_value, size_t destination_buffer_length)
121
+ const char* source,
122
+ size_t source_length,
123
+ VALUE destination_value,
124
+ size_t destination_buffer_length,
125
+ bool gvl)
89
126
  {
90
- lzws_result_t result;
91
127
  lzws_ext_result_t ext_result;
128
+ lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*) source;
129
+ size_t remaining_source_length = source_length;
130
+ size_t destination_length = 0;
131
+ size_t remaining_destination_buffer_length = destination_buffer_length;
92
132
 
93
- lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*)source;
94
- size_t remaining_source_length = source_length;
133
+ compress_args_t args = {
134
+ .state_ptr = state_ptr,
135
+ .remaining_source_ptr = &remaining_source,
136
+ .remaining_source_length_ptr = &remaining_source_length};
95
137
 
96
- size_t destination_length = 0;
97
- size_t remaining_destination_buffer_length = destination_buffer_length;
138
+ BUFFERED_COMPRESS(gvl, compress_wrapper, args);
98
139
 
99
- BUFFERED_COMPRESS(lzws_compress, state_ptr, &remaining_source, &remaining_source_length);
100
- BUFFERED_COMPRESS(lzws_compressor_finish, state_ptr);
140
+ compressor_finish_args_t finish_args = {.state_ptr = state_ptr};
141
+ BUFFERED_COMPRESS(gvl, compressor_finish_wrapper, finish_args);
101
142
 
102
143
  int exception;
103
144
 
@@ -111,17 +152,15 @@ static inline lzws_ext_result_t compress(
111
152
 
112
153
  VALUE lzws_ext_compress_string(VALUE LZWS_EXT_UNUSED(self), VALUE source_value, VALUE options)
113
154
  {
114
- GET_SOURCE_DATA(source_value);
155
+ Check_Type(source_value, T_STRING);
115
156
  Check_Type(options, T_HASH);
157
+ LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
158
+ LZWS_EXT_GET_BOOL_OPTION(options, gvl);
116
159
  LZWS_EXT_GET_COMPRESSOR_OPTIONS(options);
117
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
118
160
 
119
161
  lzws_compressor_state_t* state_ptr;
120
162
 
121
- lzws_result_t result = lzws_compressor_get_initial_state(
122
- &state_ptr,
123
- without_magic_header, max_code_bit_length, block_mode, msb, unaligned_bit_groups, quiet);
124
-
163
+ lzws_result_t result = lzws_compressor_get_initial_state(&state_ptr, &compressor_options);
125
164
  if (result != 0) {
126
165
  switch (result) {
127
166
  case LZWS_COMPRESSOR_ALLOCATE_FAILED:
@@ -145,10 +184,11 @@ VALUE lzws_ext_compress_string(VALUE LZWS_EXT_UNUSED(self), VALUE source_value,
145
184
  lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
146
185
  }
147
186
 
148
- lzws_ext_result_t ext_result = compress(
149
- state_ptr,
150
- source, source_length,
151
- destination_value, destination_buffer_length);
187
+ const char* source = RSTRING_PTR(source_value);
188
+ size_t source_length = RSTRING_LEN(source_value);
189
+
190
+ lzws_ext_result_t ext_result =
191
+ compress(state_ptr, source, source_length, destination_value, destination_buffer_length, gvl);
152
192
 
153
193
  lzws_compressor_free_state(state_ptr);
154
194
 
@@ -161,33 +201,60 @@ VALUE lzws_ext_compress_string(VALUE LZWS_EXT_UNUSED(self), VALUE source_value,
161
201
 
162
202
  // -- decompress --
163
203
 
204
+ typedef struct
205
+ {
206
+ lzws_decompressor_state_t* state_ptr;
207
+ lzws_ext_byte_t** remaining_source_ptr;
208
+ size_t* remaining_source_length_ptr;
209
+ lzws_ext_byte_t* remaining_destination_buffer;
210
+ size_t* remaining_destination_buffer_length_ptr;
211
+ lzws_result_t result;
212
+ } decompress_args_t;
213
+
214
+ static inline void* decompress_wrapper(void* data)
215
+ {
216
+ decompress_args_t* args = data;
217
+
218
+ args->result = lzws_decompress(
219
+ args->state_ptr,
220
+ args->remaining_source_ptr,
221
+ args->remaining_source_length_ptr,
222
+ &args->remaining_destination_buffer,
223
+ args->remaining_destination_buffer_length_ptr);
224
+
225
+ return NULL;
226
+ }
227
+
164
228
  static inline lzws_ext_result_t decompress(
165
229
  lzws_decompressor_state_t* state_ptr,
166
- const char* source, size_t source_length,
167
- VALUE destination_value, size_t destination_buffer_length)
230
+ const char* source,
231
+ size_t source_length,
232
+ VALUE destination_value,
233
+ size_t destination_buffer_length,
234
+ bool gvl)
168
235
  {
169
- lzws_result_t result;
170
236
  lzws_ext_result_t ext_result;
237
+ lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*) source;
238
+ size_t remaining_source_length = source_length;
239
+ size_t destination_length = 0;
240
+ size_t remaining_destination_buffer_length = destination_buffer_length;
171
241
 
172
- lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*)source;
173
- size_t remaining_source_length = source_length;
174
-
175
- size_t destination_length = 0;
176
- size_t remaining_destination_buffer_length = destination_buffer_length;
242
+ decompress_args_t args = {
243
+ .state_ptr = state_ptr,
244
+ .remaining_source_ptr = &remaining_source,
245
+ .remaining_source_length_ptr = &remaining_source_length};
177
246
 
178
247
  while (true) {
179
- lzws_ext_byte_t* remaining_destination_buffer = (lzws_ext_byte_t*)RSTRING_PTR(destination_value) + destination_length;
180
- size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
181
-
182
- result = lzws_decompress(
183
- state_ptr,
184
- &remaining_source, &remaining_source_length,
185
- &remaining_destination_buffer, &remaining_destination_buffer_length);
186
-
187
- if (
188
- result != 0 &&
189
- result != LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
190
- switch (result) {
248
+ lzws_ext_byte_t* remaining_destination_buffer =
249
+ (lzws_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
250
+ size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
251
+
252
+ args.remaining_destination_buffer = remaining_destination_buffer;
253
+ args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
254
+
255
+ LZWS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
256
+ if (args.result != 0 && args.result != LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
257
+ switch (args.result) {
191
258
  case LZWS_DECOMPRESSOR_INVALID_MAGIC_HEADER:
192
259
  case LZWS_DECOMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH:
193
260
  return LZWS_EXT_ERROR_VALIDATE_FAILED;
@@ -200,10 +267,9 @@ static inline lzws_ext_result_t decompress(
200
267
 
201
268
  destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length;
202
269
 
203
- if (result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
270
+ if (args.result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
204
271
  ext_result = increase_destination_buffer(
205
- destination_value, destination_length,
206
- &remaining_destination_buffer_length, destination_buffer_length);
272
+ destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
207
273
 
208
274
  if (ext_result != 0) {
209
275
  return ext_result;
@@ -227,17 +293,15 @@ static inline lzws_ext_result_t decompress(
227
293
 
228
294
  VALUE lzws_ext_decompress_string(VALUE LZWS_EXT_UNUSED(self), VALUE source_value, VALUE options)
229
295
  {
230
- GET_SOURCE_DATA(source_value);
296
+ Check_Type(source_value, T_STRING);
231
297
  Check_Type(options, T_HASH);
298
+ LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
299
+ LZWS_EXT_GET_BOOL_OPTION(options, gvl);
232
300
  LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
233
- LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
234
301
 
235
302
  lzws_decompressor_state_t* state_ptr;
236
303
 
237
- lzws_result_t result = lzws_decompressor_get_initial_state(
238
- &state_ptr,
239
- without_magic_header, msb, unaligned_bit_groups, quiet);
240
-
304
+ lzws_result_t result = lzws_decompressor_get_initial_state(&state_ptr, &decompressor_options);
241
305
  if (result != 0) {
242
306
  switch (result) {
243
307
  case LZWS_DECOMPRESSOR_ALLOCATE_FAILED:
@@ -259,10 +323,11 @@ VALUE lzws_ext_decompress_string(VALUE LZWS_EXT_UNUSED(self), VALUE source_value
259
323
  lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
260
324
  }
261
325
 
262
- lzws_ext_result_t ext_result = decompress(
263
- state_ptr,
264
- source, source_length,
265
- destination_value, destination_buffer_length);
326
+ const char* source = RSTRING_PTR(source_value);
327
+ size_t source_length = RSTRING_LEN(source_value);
328
+
329
+ lzws_ext_result_t ext_result =
330
+ decompress(state_ptr, source, source_length, destination_value, destination_buffer_length, gvl);
266
331
 
267
332
  lzws_decompressor_free_state(state_ptr);
268
333
 
@@ -273,6 +338,8 @@ VALUE lzws_ext_decompress_string(VALUE LZWS_EXT_UNUSED(self), VALUE source_value
273
338
  return destination_value;
274
339
  }
275
340
 
341
+ // -- exports --
342
+
276
343
  void lzws_ext_string_exports(VALUE root_module)
277
344
  {
278
345
  rb_define_module_function(root_module, "_native_compress_string", RUBY_METHOD_FUNC(lzws_ext_compress_string), 2);
@@ -20,6 +20,8 @@ module LZWS
20
20
  open_files(source, destination) do |source_io, destination_io|
21
21
  LZWS._native_compress_io source_io, destination_io, options
22
22
  end
23
+
24
+ nil
23
25
  end
24
26
 
25
27
  def self.decompress(source, destination, options = {})
@@ -31,6 +33,8 @@ module LZWS
31
33
  open_files(source, destination) do |source_io, destination_io|
32
34
  LZWS._native_decompress_io source_io, destination_io, options
33
35
  end
36
+
37
+ nil
34
38
  end
35
39
 
36
40
  private_class_method def self.open_files(source, destination, &_block)
@@ -8,24 +8,26 @@ require_relative "validation"
8
8
 
9
9
  module LZWS
10
10
  module Option
11
- # Default options will be compatible with UNIX compress.
12
-
13
- DEFAULT_BUFFER_LENGTH = 0
14
- LOWEST_MAX_CODE_BIT_LENGTH = 9
15
- BIGGEST_MAX_CODE_BIT_LENGTH = 16
16
-
17
- DECOMPRESSOR_DEFAULTS = {
18
- :without_magic_header => false,
19
- :msb => false,
20
- :unaligned_bit_groups => false,
21
- :quiet => false
11
+ DEFAULT_BUFFER_LENGTH = 0
12
+
13
+ COMPRESSOR_DEFAULTS = {
14
+ :gvl => false,
15
+ :max_code_bit_length => nil,
16
+ :without_magic_header => nil,
17
+ :block_mode => nil,
18
+ :msb => nil,
19
+ :unaligned_bit_groups => nil,
20
+ :quiet => nil
22
21
  }
23
22
  .freeze
24
23
 
25
- COMPRESSOR_DEFAULTS = DECOMPRESSOR_DEFAULTS.merge(
26
- :max_code_bit_length => BIGGEST_MAX_CODE_BIT_LENGTH,
27
- :block_mode => true
28
- )
24
+ DECOMPRESSOR_DEFAULTS = {
25
+ :gvl => false,
26
+ :without_magic_header => nil,
27
+ :msb => nil,
28
+ :unaligned_bit_groups => nil,
29
+ :quiet => nil
30
+ }
29
31
  .freeze
30
32
 
31
33
  def self.get_compressor_options(options, buffer_length_names)
@@ -36,17 +38,29 @@ module LZWS
36
38
 
37
39
  buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
38
40
 
41
+ Validation.validate_bool options[:gvl]
42
+
39
43
  max_code_bit_length = options[:max_code_bit_length]
40
- Validation.validate_positive_integer max_code_bit_length
44
+ unless max_code_bit_length.nil?
45
+ Validation.validate_positive_integer max_code_bit_length
46
+ raise ValidateError, "invalid max code bit length" if
47
+ max_code_bit_length < LOWEST_MAX_CODE_BIT_LENGTH || max_code_bit_length > BIGGEST_MAX_CODE_BIT_LENGTH
48
+ end
49
+
50
+ without_magic_header = options[:without_magic_header]
51
+ Validation.validate_bool without_magic_header unless without_magic_header.nil?
41
52
 
42
- raise ValidateError, "invalid max code bit length" if
43
- max_code_bit_length < LOWEST_MAX_CODE_BIT_LENGTH || max_code_bit_length > BIGGEST_MAX_CODE_BIT_LENGTH
53
+ block_mode = options[:block_mode]
54
+ Validation.validate_bool block_mode unless block_mode.nil?
44
55
 
45
- Validation.validate_bool options[:without_magic_header]
46
- Validation.validate_bool options[:block_mode]
47
- Validation.validate_bool options[:msb]
48
- Validation.validate_bool options[:unaligned_bit_groups]
49
- Validation.validate_bool options[:quiet]
56
+ msb = options[:msb]
57
+ Validation.validate_bool msb unless msb.nil?
58
+
59
+ unaligned_bit_groups = options[:unaligned_bit_groups]
60
+ Validation.validate_bool unaligned_bit_groups unless unaligned_bit_groups.nil?
61
+
62
+ quiet = options[:quiet]
63
+ Validation.validate_bool quiet unless quiet.nil?
50
64
 
51
65
  options
52
66
  end
@@ -59,10 +73,19 @@ module LZWS
59
73
 
60
74
  buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
61
75
 
62
- Validation.validate_bool options[:without_magic_header]
63
- Validation.validate_bool options[:msb]
64
- Validation.validate_bool options[:unaligned_bit_groups]
65
- Validation.validate_bool options[:quiet]
76
+ Validation.validate_bool options[:gvl]
77
+
78
+ without_magic_header = options[:without_magic_header]
79
+ Validation.validate_bool without_magic_header unless without_magic_header.nil?
80
+
81
+ msb = options[:msb]
82
+ Validation.validate_bool msb unless msb.nil?
83
+
84
+ unaligned_bit_groups = options[:unaligned_bit_groups]
85
+ Validation.validate_bool unaligned_bit_groups unless unaligned_bit_groups.nil?
86
+
87
+ quiet = options[:quiet]
88
+ Validation.validate_bool quiet unless quiet.nil?
66
89
 
67
90
  options
68
91
  end