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.
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);