ruby-lzws 1.1.7 → 1.4.0

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