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.
@@ -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