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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fc8861bd91fe484c375cdeae3ad55e478727e8a1314117fb3897cef408bd401
4
- data.tar.gz: 9b7a0d9cd62930a12250641599638d80abb34737bae20842109d91f1dfee84a8
3
+ metadata.gz: 46de1059ebc7e81a3c93869a70801e20571e99631a0a9a8acc0cad9b06e9c21f
4
+ data.tar.gz: c4d1d3859bd374404b496b9ae393f34b08b49bf94655e420862545fd8949cc12
5
5
  SHA512:
6
- metadata.gz: 880eb17f48cca872b77a56936aedebe4aa416eb971e51743550e0bd02c473568fb638d412deab64c522fa84895732c9f91da338a7d4f79bd3ac4c382f35326eb
7
- data.tar.gz: e29e72c646f05e55ec4411a06e4be7122581962d9fe46164bc6bbaeefd1e874595ad74783503f76bf049096730043032976c8595e2d7903d9acb3ab9bb39b8cc
6
+ metadata.gz: 88f2f3627fb6f98fffc6c1289301a9362c6ab22edc7de42732a90c85b1065bd2e3ee73547dbab0ee1c40d14c3490053f43d36d7b67abb25aa6ec2e938211e95e
7
+ data.tar.gz: e6b97fea5d39bd2ee8b4e9ad43d16453f0640536c86dd9e0d425443c3a48a5bb3bf99c5bb452e4065f3c21489572a4bf05a9809b1eccfd7ef39773a1eea0d05d
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # Ruby bindings for lzws library
2
2
 
3
- | Travis | AppVeyor | Cirrus | Circle | Codecov |
4
- | :---: | :---: | :---: | :---: | :---: |
5
- | [![Travis test status](https://travis-ci.com/andrew-aladev/ruby-lzws.svg?branch=master)](https://travis-ci.com/andrew-aladev/ruby-lzws) | [![AppVeyor test status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ruby-lzws?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ruby-lzws/branch/master) | [![Cirrus test status](https://api.cirrus-ci.com/github/andrew-aladev/ruby-lzws.svg?branch=master)](https://cirrus-ci.com/github/andrew-aladev/ruby-lzws) | [![Circle test status](https://circleci.com/gh/andrew-aladev/ruby-lzws/tree/master.svg?style=shield)](https://circleci.com/gh/andrew-aladev/ruby-lzws/tree/master) | [![Codecov](https://codecov.io/gh/andrew-aladev/ruby-lzws/branch/master/graph/badge.svg)](https://codecov.io/gh/andrew-aladev/ruby-lzws) |
3
+ | Travis | AppVeyor | Circle | Codecov | Gem |
4
+ | :---: | :---: | :---: | :---: | :---: |
5
+ | [![Travis test status](https://travis-ci.com/andrew-aladev/ruby-lzws.svg?branch=master)](https://travis-ci.com/andrew-aladev/ruby-lzws) | [![AppVeyor test status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ruby-lzws?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ruby-lzws/branch/master) | [![Circle test status](https://circleci.com/gh/andrew-aladev/ruby-lzws/tree/master.svg?style=shield)](https://circleci.com/gh/andrew-aladev/ruby-lzws/tree/master) | [![Codecov](https://codecov.io/gh/andrew-aladev/ruby-lzws/branch/master/graph/badge.svg)](https://codecov.io/gh/andrew-aladev/ruby-lzws) | [![Gem](https://img.shields.io/gem/v/ruby-lzws.svg)](https://rubygems.org/gems/ruby-lzws) |
6
6
 
7
7
  See [lzws library](https://github.com/andrew-aladev/lzws).
8
8
 
9
9
  ## Installation
10
10
 
11
- Please install lzws library first, use latest 1.3.0+ version.
11
+ Please install lzws library first, use latest 1.4.0+ version.
12
12
 
13
13
  ```sh
14
14
  gem install ruby-lzws
@@ -21,6 +21,8 @@ rake gem
21
21
  gem install pkg/ruby-lzws-*.gem
22
22
  ```
23
23
 
24
+ You can also use [overlay](https://github.com/andrew-aladev/overlay) for gentoo.
25
+
24
26
  ## Usage
25
27
 
26
28
  There are simple APIs: `String` and `File`. Also you can use generic streaming API: `Stream::Writer` and `Stream::Reader`.
@@ -36,10 +38,31 @@ LZWS::File.decompress "file.txt.Z", "file.txt"
36
38
 
37
39
  LZWS::Stream::Writer.open("file.txt.Z") { |writer| writer << "TOBEORNOTTOBEORTOBEORNOT" }
38
40
  puts LZWS::Stream::Reader.open("file.txt.Z") { |reader| reader.read }
41
+
42
+ writer = LZWS::Stream::Writer.new output_socket
43
+ begin
44
+ bytes_written = writer.write_nonblock "TOBEORNOTTOBEORTOBEORNOT"
45
+ # handle "bytes_written"
46
+ rescue IO::WaitWritable
47
+ # handle wait
48
+ ensure
49
+ writer.close
50
+ end
51
+
52
+ reader = LZWS::Stream::Reader.new input_socket
53
+ begin
54
+ puts reader.read_nonblock(512)
55
+ rescue IO::WaitReadable
56
+ # handle wait
57
+ rescue ::EOFError
58
+ # handle eof
59
+ ensure
60
+ reader.close
61
+ end
39
62
  ```
40
63
 
41
- You can create and read `tar.Z` archives with `minitar` for example.
42
- LZWS is compatible with UNIX compress (with default options).
64
+ You can create and read `tar.Z` archives with [minitar](https://github.com/halostatue/minitar) for example.
65
+ LZWS is compatible with [UNIX compress](https://en.wikipedia.org/wiki/Compress) (with default options).
43
66
 
44
67
  ```ruby
45
68
  require "lzws"
@@ -61,66 +84,51 @@ LZWS::Stream::Reader.open "file.tar.Z" do |reader|
61
84
  end
62
85
  ```
63
86
 
64
- ## Options
65
-
66
- Each API supports several options:
67
-
68
- ```
69
- :source_buffer_length
70
- :destination_buffer_length
71
- ```
72
-
73
- There are internal buffers for compressed and decompressed data.
74
- For example you want to use 1 KB as source buffer length for compressor - please use 256 B as destination buffer length.
75
- You want to use 256 B as source buffer length for decompressor - please use 1 KB as destination buffer length.
76
-
77
- Values: 0, 2 - infinity, default value: 0.
78
- 0 means automatic buffer length selection.
79
- 1 byte is not enough, 2 bytes is minimal buffer length.
87
+ You can also use `Content-Encoding: compress` with [sinatra](http://sinatrarb.com):
80
88
 
81
- ```
82
- :max_code_bit_length
83
- ```
84
-
85
- Values: `LZWS::Option::LOWEST_MAX_CODE_BIT_LENGTH` - `LZWS::Option::BIGGEST_MAX_CODE_BIT_LENGTH`, default value: `LZWS::Option::BIGGEST_MAX_CODE_BIT_LENGTH`.
86
-
87
- ```
88
- :block_mode
89
- ```
90
-
91
- Values: true/false, default value: true.
92
-
93
- ```
94
- :without_magic_header
95
- ```
96
-
97
- Values: true/false, default value: false.
89
+ ```ruby
90
+ require "lzws"
91
+ require "sinatra"
98
92
 
99
- ```
100
- :msb
93
+ get "/" do
94
+ headers["Content-Encoding"] = "compress"
95
+ LZWS::String.compress "TOBEORNOTTOBEORTOBEORNOT"
96
+ end
101
97
  ```
102
98
 
103
- Values: true/false, default value: false.
99
+ ## Options
104
100
 
105
- ```
106
- :unaligned_bit_groups
107
- ```
101
+ | Option | Values | Default | Description |
102
+ |-----------------------------|------------|----------|-------------|
103
+ | `source_buffer_length` | 0, 2 - inf | 0 (auto) | internal buffer length for source data |
104
+ | `destination_buffer_length` | 0, 2 - inf | 0 (auto) | internal buffer length for description data |
105
+ | `gvl` | true/false | false | enables global VM lock where possible |
106
+ | `max_code_bit_length` | 9 - 16 | 16 | max code bit length |
107
+ | `block_mode` | true/false | true | enables block mode |
108
+ | `without_magic_header` | true/false | false | disables magic header |
109
+ | `msb` | true/false | false | enables most significant bit mode |
110
+ | `unaligned_bit_groups` | true/false | false | enables unaligned bit groups |
111
+ | `quiet` | true/false | false | disables lzws library logging |
108
112
 
109
- Values: true/false, default value: false.
113
+ There are internal buffers for compressed and decompressed data.
114
+ For example you want to use 1 KB as `source_buffer_length` for compressor - please use 256 B as `destination_buffer_length`.
115
+ You want to use 256 B as `source_buffer_length` for decompressor - please use 1 KB as `destination_buffer_length`.
110
116
 
111
- ```
112
- :quiet
113
- ```
117
+ `gvl` is disabled by default, this mode allows running multiple compressors/decompressors in different threads simultaneously.
118
+ Please consider enabling `gvl` if you don't want to launch processors in separate threads.
119
+ If `gvl` is enabled ruby won't waste time on acquiring/releasing VM lock.
114
120
 
115
- Values: true/false, default value: false.
116
- Disables lzws library logging.
121
+ You can also read lzws docs for more info about options.
117
122
 
118
- Please read lzws docs for more info about options.
123
+ | Option | Related constants |
124
+ |-----------------------|-------------------|
125
+ | `max_code_bit_length` | `LZWS::Option::LOWEST_MAX_CODE_BIT_LENGTH` = 9, `LZWS::Option::BIGGEST_MAX_CODE_BIT_LENGTH` = 16 |
119
126
 
120
127
  Possible compressor options:
121
128
  ```
122
129
  :source_buffer_length
123
130
  :destination_buffer_length
131
+ :gvl
124
132
  :max_code_bit_length
125
133
  :block_mode
126
134
  :without_magic_header
@@ -133,6 +141,7 @@ Possible decompressor options:
133
141
  ```
134
142
  :source_buffer_length
135
143
  :destination_buffer_length
144
+ :gvl
136
145
  :without_magic_header
137
146
  :msb
138
147
  :unaligned_bit_groups
@@ -148,18 +157,6 @@ data = LZWS::String.compress "TOBEORNOTTOBEORTOBEORNOT", :msb => true
148
157
  puts LZWS::String.decompress(data, :msb => true)
149
158
  ```
150
159
 
151
- Default options are compatible with UNIX compress (`Content-Encoding: compress`):
152
-
153
- ```ruby
154
- require "lzws"
155
- require "sinatra"
156
-
157
- get "/" do
158
- headers["Content-Encoding"] = "compress"
159
- LZWS::String.compress "TOBEORNOTTOBEORTOBEORNOT"
160
- end
161
- ```
162
-
163
160
  Please read more about compatibility in lzws docs.
164
161
 
165
162
  ## String
@@ -333,14 +330,18 @@ See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
333
330
 
334
331
  Typical helpers, see [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
335
332
 
333
+ ## Thread safety
334
+
335
+ `:gvl` option is disabled by default, you can use bindings effectively in multiple threads.
336
+ Please be careful: bindings are not thread safe.
337
+ You should lock all shared data between threads.
338
+
336
339
  ## CI
337
340
 
338
- See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
339
341
  Please visit [scripts/test-images](scripts/test-images).
340
- You can run this test script using many native and cross images.
341
-
342
- Cirrus CI uses `x86_64-pc-linux-gnu` image, Circle CI - `x86_64-gentoo-linux-musl` image.
342
+ See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
343
+ You can run this script using many native and cross images.
343
344
 
344
345
  ## License
345
346
 
346
- MIT license, see LICENSE and AUTHORS.
347
+ MIT license, see [LICENSE](LICENSE) and [AUTHORS](AUTHORS).
@@ -3,6 +3,8 @@
3
3
 
4
4
  require "mkmf"
5
5
 
6
+ have_func "rb_thread_call_without_gvl", "ruby/thread.h"
7
+
6
8
  def require_header(name, types = [])
7
9
  abort "Can't find #{name} header" unless find_header name
8
10
 
@@ -13,10 +15,10 @@ end
13
15
 
14
16
  require_header "lzws/buffer.h"
15
17
  require_header "lzws/common.h", %w[lzws_result_t]
16
- require_header "lzws/compressor/common.h"
18
+ require_header "lzws/compressor/common.h", %w[lzws_compressor_options_t]
17
19
  require_header "lzws/compressor/main.h"
18
20
  require_header "lzws/compressor/state.h", %w[lzws_compressor_state_t]
19
- require_header "lzws/decompressor/common.h"
21
+ require_header "lzws/decompressor/common.h", %w[lzws_decompressor_options_t]
20
22
  require_header "lzws/decompressor/main.h"
21
23
  require_header "lzws/decompressor/state.h", %w[lzws_decompressor_state_t]
22
24
  require_header "lzws/file.h"
@@ -66,6 +68,13 @@ $srcs = %w[
66
68
  .map { |name| "src/#{extension_name}/#{name}.c" }
67
69
  .freeze
68
70
 
71
+ # Removing library duplicates.
72
+ $libs = $libs.split(%r{\s})
73
+ .reject(&:empty?)
74
+ .sort
75
+ .uniq
76
+ .join " "
77
+
69
78
  if ENV["CI"] || ENV["COVERAGE"]
70
79
  $CFLAGS << " --coverage"
71
80
  $LDFLAGS << " --coverage"
@@ -12,10 +12,11 @@ VALUE lzws_ext_create_string_buffer(VALUE length)
12
12
  return rb_str_new(NULL, NUM2SIZET(length));
13
13
  }
14
14
 
15
- VALUE lzws_ext_resize_string_buffer(VALUE args)
15
+ VALUE lzws_ext_resize_string_buffer(VALUE buffer_args)
16
16
  {
17
- VALUE buffer = rb_ary_entry(args, 0);
18
- VALUE length = rb_ary_entry(args, 1);
17
+ VALUE buffer = rb_ary_entry(buffer_args, 0);
18
+ VALUE length = rb_ary_entry(buffer_args, 1);
19
+
19
20
  return rb_str_resize(buffer, NUM2SIZET(length));
20
21
  }
21
22
 
@@ -23,8 +24,21 @@ void lzws_ext_buffer_exports(VALUE root_module)
23
24
  {
24
25
  VALUE module = rb_define_module_under(root_module, "Buffer");
25
26
 
26
- rb_define_const(module, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR", SIZET2NUM(LZWS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR));
27
- rb_define_const(module, "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR", SIZET2NUM(LZWS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR));
28
- rb_define_const(module, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR", SIZET2NUM(LZWS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR));
29
- rb_define_const(module, "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR", SIZET2NUM(LZWS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR));
27
+ rb_define_const(
28
+ module, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR", SIZET2NUM(LZWS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR));
29
+
30
+ rb_define_const(
31
+ module,
32
+ "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR",
33
+ SIZET2NUM(LZWS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR));
34
+
35
+ rb_define_const(
36
+ module,
37
+ "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR",
38
+ SIZET2NUM(LZWS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR));
39
+
40
+ rb_define_const(
41
+ module,
42
+ "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR",
43
+ SIZET2NUM(LZWS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR));
30
44
  }
@@ -11,12 +11,12 @@ VALUE lzws_ext_create_string_buffer(VALUE length);
11
11
  #define LZWS_EXT_CREATE_STRING_BUFFER(buffer, length, exception) \
12
12
  VALUE buffer = rb_protect(lzws_ext_create_string_buffer, SIZET2NUM(length), &exception);
13
13
 
14
- VALUE lzws_ext_resize_string_buffer(VALUE args);
14
+ VALUE lzws_ext_resize_string_buffer(VALUE buffer_args);
15
15
 
16
- #define LZWS_EXT_RESIZE_STRING_BUFFER(buffer, length, exception) \
17
- VALUE args = rb_ary_new_from_args(2, buffer, SIZET2NUM(length)); \
18
- buffer = rb_protect(lzws_ext_resize_string_buffer, args, &exception); \
19
- RB_GC_GUARD(args);
16
+ #define LZWS_EXT_RESIZE_STRING_BUFFER(buffer, length, exception) \
17
+ VALUE buffer_args = rb_ary_new_from_args(2, buffer, SIZET2NUM(length)); \
18
+ buffer = rb_protect(lzws_ext_resize_string_buffer, buffer_args, &exception); \
19
+ RB_GC_GUARD(buffer_args);
20
20
 
21
21
  void lzws_ext_buffer_exports(VALUE root_module);
22
22
 
@@ -9,7 +9,8 @@
9
9
 
10
10
  // Results for errors listed in "lib/lzws/error" used in c extension.
11
11
 
12
- enum {
12
+ enum
13
+ {
13
14
  LZWS_EXT_ERROR_ALLOCATE_FAILED = 1,
14
15
  LZWS_EXT_ERROR_VALIDATE_FAILED,
15
16
 
@@ -0,0 +1,24 @@
1
+ // Ruby bindings for lzws library.
2
+ // Copyright (c) 2019 AUTHORS, MIT License.
3
+
4
+ #if !defined(LZWS_EXT_GVL_H)
5
+ #define LZWS_EXT_GVL_H
6
+
7
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
8
+
9
+ #include "ruby/thread.h"
10
+
11
+ #define LZWS_EXT_GVL_WRAP(gvl, function, data) \
12
+ if (gvl) { \
13
+ function((void*) data); \
14
+ } else { \
15
+ rb_thread_call_without_gvl(function, (void*) data, RUBY_UBF_IO, NULL); \
16
+ }
17
+
18
+ #else
19
+
20
+ #define LZWS_EXT_GVL_WRAP(_gvl, function, data) function((void*) data);
21
+
22
+ #endif
23
+
24
+ #endif // LZWS_EXT_GVL_H
@@ -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);