ruby-bzs 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #if !defined(BZS_EXT_STREAM_DECOMPRESSOR_H)
5
+ #define BZS_EXT_STREAM_DECOMPRESSOR_H
6
+
7
+ #include <bzlib.h>
8
+ #include <stdbool.h>
9
+
10
+ #include "bzs_ext/common.h"
11
+ #include "ruby.h"
12
+
13
+ typedef struct
14
+ {
15
+ bz_stream* stream_ptr;
16
+ bzs_ext_byte_t* destination_buffer;
17
+ size_t destination_buffer_length;
18
+ bzs_ext_byte_t* remaining_destination_buffer;
19
+ size_t remaining_destination_buffer_length;
20
+ bool gvl;
21
+ } bzs_ext_decompressor_t;
22
+
23
+ VALUE bzs_ext_allocate_decompressor(VALUE klass);
24
+ VALUE bzs_ext_initialize_decompressor(VALUE self, VALUE options);
25
+ VALUE bzs_ext_decompress(VALUE self, VALUE source);
26
+ VALUE bzs_ext_decompressor_read_result(VALUE self);
27
+ VALUE bzs_ext_decompressor_close(VALUE self);
28
+
29
+ void bzs_ext_decompressor_exports(VALUE root_module);
30
+
31
+ #endif // BZS_EXT_STREAM_DECOMPRESSOR_H
@@ -0,0 +1,340 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #include "bzs_ext/string.h"
5
+
6
+ #include <bzlib.h>
7
+
8
+ #include "bzs_ext/buffer.h"
9
+ #include "bzs_ext/common.h"
10
+ #include "bzs_ext/error.h"
11
+ #include "bzs_ext/gvl.h"
12
+ #include "bzs_ext/macro.h"
13
+ #include "bzs_ext/option.h"
14
+ #include "bzs_ext/utils.h"
15
+
16
+ // -- buffer --
17
+
18
+ static inline bzs_ext_result_t increase_destination_buffer(
19
+ VALUE destination_value,
20
+ size_t destination_length,
21
+ size_t* remaining_destination_buffer_length_ptr,
22
+ size_t destination_buffer_length)
23
+ {
24
+ if (*remaining_destination_buffer_length_ptr == destination_buffer_length) {
25
+ // We want to write more data at once, than buffer has.
26
+ return BZS_EXT_ERROR_NOT_ENOUGH_DESTINATION_BUFFER;
27
+ }
28
+
29
+ int exception;
30
+
31
+ BZS_EXT_RESIZE_STRING_BUFFER(destination_value, destination_length + destination_buffer_length, exception);
32
+ if (exception != 0) {
33
+ return BZS_EXT_ERROR_ALLOCATE_FAILED;
34
+ }
35
+
36
+ *remaining_destination_buffer_length_ptr = destination_buffer_length;
37
+
38
+ return 0;
39
+ }
40
+
41
+ // -- compress --
42
+
43
+ typedef struct
44
+ {
45
+ bz_stream* stream_ptr;
46
+ int stream_action;
47
+ bzs_ext_byte_t** remaining_source_ptr;
48
+ size_t* remaining_source_length_ptr;
49
+ bzs_ext_byte_t* remaining_destination_buffer;
50
+ size_t* remaining_destination_buffer_length_ptr;
51
+ bzs_result_t result;
52
+ } compress_args_t;
53
+
54
+ static inline void* compress_wrapper(void* data)
55
+ {
56
+ compress_args_t* args = data;
57
+
58
+ args->stream_ptr->next_in = (char*) *args->remaining_source_ptr;
59
+ args->stream_ptr->avail_in = bzs_consume_size(*args->remaining_source_length_ptr);
60
+ args->stream_ptr->next_out = (char*) args->remaining_destination_buffer;
61
+ args->stream_ptr->avail_out = bzs_consume_size(*args->remaining_destination_buffer_length_ptr);
62
+
63
+ args->result = BZ2_bzCompress(args->stream_ptr, args->stream_action);
64
+
65
+ *args->remaining_source_ptr = (bzs_ext_byte_t*) args->stream_ptr->next_in;
66
+ *args->remaining_source_length_ptr = args->stream_ptr->avail_in;
67
+ *args->remaining_destination_buffer_length_ptr = args->stream_ptr->avail_out;
68
+
69
+ return NULL;
70
+ }
71
+
72
+ #define BUFFERED_COMPRESS(gvl, args, RUN_OK) \
73
+ while (true) { \
74
+ bzs_ext_byte_t* remaining_destination_buffer = \
75
+ (bzs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length; \
76
+ size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length; \
77
+ \
78
+ args.remaining_destination_buffer = remaining_destination_buffer; \
79
+ args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length; \
80
+ \
81
+ BZS_EXT_GVL_WRAP(gvl, compress_wrapper, &args); \
82
+ if (args.result != RUN_OK && args.result != BZ_PARAM_ERROR && args.result != BZ_STREAM_END) { \
83
+ return bzs_ext_get_error(args.result); \
84
+ } \
85
+ \
86
+ destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length; \
87
+ \
88
+ if (args.result == BZ_STREAM_END) { \
89
+ break; \
90
+ } \
91
+ \
92
+ if (remaining_source_length != 0 || remaining_destination_buffer_length == 0) { \
93
+ ext_result = increase_destination_buffer( \
94
+ destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length); \
95
+ \
96
+ if (ext_result != 0) { \
97
+ return ext_result; \
98
+ } \
99
+ \
100
+ continue; \
101
+ } \
102
+ \
103
+ break; \
104
+ }
105
+
106
+ static inline bzs_ext_result_t compress(
107
+ bz_stream* stream_ptr,
108
+ const char* source,
109
+ size_t source_length,
110
+ VALUE destination_value,
111
+ size_t destination_buffer_length,
112
+ bool gvl)
113
+ {
114
+ bzs_ext_result_t ext_result;
115
+ bzs_ext_byte_t* remaining_source = (bzs_ext_byte_t*) source;
116
+ size_t remaining_source_length = source_length;
117
+ size_t destination_length = 0;
118
+ size_t remaining_destination_buffer_length = destination_buffer_length;
119
+
120
+ compress_args_t run_args = {
121
+ .stream_ptr = stream_ptr,
122
+ .stream_action = BZ_RUN,
123
+ .remaining_source_ptr = &remaining_source,
124
+ .remaining_source_length_ptr = &remaining_source_length};
125
+ BUFFERED_COMPRESS(gvl, run_args, BZ_RUN_OK);
126
+
127
+ compress_args_t finish_args = {
128
+ .stream_ptr = stream_ptr,
129
+ .stream_action = BZ_FINISH,
130
+ .remaining_source_ptr = &remaining_source,
131
+ .remaining_source_length_ptr = &remaining_source_length};
132
+ BUFFERED_COMPRESS(gvl, finish_args, BZ_FINISH_OK);
133
+
134
+ int exception;
135
+
136
+ BZS_EXT_RESIZE_STRING_BUFFER(destination_value, destination_length, exception);
137
+ if (exception != 0) {
138
+ return BZS_EXT_ERROR_ALLOCATE_FAILED;
139
+ }
140
+
141
+ return 0;
142
+ }
143
+
144
+ VALUE bzs_ext_compress_string(VALUE BZS_EXT_UNUSED(self), VALUE source_value, VALUE options)
145
+ {
146
+ Check_Type(source_value, T_STRING);
147
+ Check_Type(options, T_HASH);
148
+ BZS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
149
+ BZS_EXT_GET_BOOL_OPTION(options, gvl);
150
+ BZS_EXT_RESOLVE_COMPRESSOR_OPTIONS(options);
151
+
152
+ bz_stream stream = {
153
+ .bzalloc = NULL,
154
+ .bzfree = NULL,
155
+ .opaque = NULL,
156
+ };
157
+
158
+ bzs_result_t result = BZ2_bzCompressInit(&stream, block_size, verbosity, work_factor);
159
+ if (result != BZ_OK) {
160
+ bzs_ext_raise_error(bzs_ext_get_error(result));
161
+ }
162
+
163
+ if (destination_buffer_length == 0) {
164
+ destination_buffer_length = BZS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR;
165
+ }
166
+
167
+ int exception;
168
+
169
+ BZS_EXT_CREATE_STRING_BUFFER(destination_value, destination_buffer_length, exception);
170
+ if (exception != 0) {
171
+ BZ2_bzCompressEnd(&stream);
172
+ bzs_ext_raise_error(BZS_EXT_ERROR_ALLOCATE_FAILED);
173
+ }
174
+
175
+ const char* source = RSTRING_PTR(source_value);
176
+ size_t source_length = RSTRING_LEN(source_value);
177
+
178
+ bzs_ext_result_t ext_result =
179
+ compress(&stream, source, source_length, destination_value, destination_buffer_length, gvl);
180
+
181
+ result = BZ2_bzCompressEnd(&stream);
182
+ if (result != BZ_OK) {
183
+ ext_result = bzs_ext_get_error(result);
184
+ }
185
+
186
+ if (ext_result != 0) {
187
+ bzs_ext_raise_error(ext_result);
188
+ }
189
+
190
+ return destination_value;
191
+ }
192
+
193
+ // -- decompress --
194
+
195
+ typedef struct
196
+ {
197
+ bz_stream* stream_ptr;
198
+ bzs_ext_byte_t** remaining_source_ptr;
199
+ size_t* remaining_source_length_ptr;
200
+ bzs_ext_byte_t* remaining_destination_buffer;
201
+ size_t* remaining_destination_buffer_length_ptr;
202
+ bzs_result_t result;
203
+ } decompress_args_t;
204
+
205
+ static inline void* decompress_wrapper(void* data)
206
+ {
207
+ decompress_args_t* args = data;
208
+
209
+ args->stream_ptr->next_in = (char*) *args->remaining_source_ptr;
210
+ args->stream_ptr->avail_in = bzs_consume_size(*args->remaining_source_length_ptr);
211
+ args->stream_ptr->next_out = (char*) args->remaining_destination_buffer;
212
+ args->stream_ptr->avail_out = bzs_consume_size(*args->remaining_destination_buffer_length_ptr);
213
+
214
+ args->result = BZ2_bzDecompress(args->stream_ptr);
215
+
216
+ *args->remaining_source_ptr = (bzs_ext_byte_t*) args->stream_ptr->next_in;
217
+ *args->remaining_source_length_ptr = args->stream_ptr->avail_in;
218
+ *args->remaining_destination_buffer_length_ptr = args->stream_ptr->avail_out;
219
+
220
+ return NULL;
221
+ }
222
+
223
+ static inline bzs_ext_result_t decompress(
224
+ bz_stream* stream_ptr,
225
+ const char* source,
226
+ size_t source_length,
227
+ VALUE destination_value,
228
+ size_t destination_buffer_length,
229
+ bool gvl)
230
+ {
231
+ bzs_ext_result_t ext_result;
232
+ bzs_ext_byte_t* remaining_source = (bzs_ext_byte_t*) source;
233
+ size_t remaining_source_length = source_length;
234
+ size_t destination_length = 0;
235
+ size_t remaining_destination_buffer_length = destination_buffer_length;
236
+
237
+ decompress_args_t args = {
238
+ .stream_ptr = stream_ptr,
239
+ .remaining_source_ptr = &remaining_source,
240
+ .remaining_source_length_ptr = &remaining_source_length};
241
+
242
+ while (true) {
243
+ bzs_ext_byte_t* remaining_destination_buffer =
244
+ (bzs_ext_byte_t*) RSTRING_PTR(destination_value) + destination_length;
245
+ size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
246
+
247
+ args.remaining_destination_buffer = remaining_destination_buffer;
248
+ args.remaining_destination_buffer_length_ptr = &remaining_destination_buffer_length;
249
+
250
+ BZS_EXT_GVL_WRAP(gvl, decompress_wrapper, &args);
251
+ if (args.result != BZ_OK && args.result != BZ_PARAM_ERROR && args.result != BZ_STREAM_END) {
252
+ return bzs_ext_get_error(args.result);
253
+ }
254
+
255
+ destination_length += prev_remaining_destination_buffer_length - remaining_destination_buffer_length;
256
+
257
+ if (args.result == BZ_STREAM_END) {
258
+ break;
259
+ }
260
+
261
+ if (remaining_source_length != 0 || remaining_destination_buffer_length == 0) {
262
+ ext_result = increase_destination_buffer(
263
+ destination_value, destination_length, &remaining_destination_buffer_length, destination_buffer_length);
264
+
265
+ if (ext_result != 0) {
266
+ return ext_result;
267
+ }
268
+
269
+ continue;
270
+ }
271
+
272
+ break;
273
+ }
274
+
275
+ int exception;
276
+
277
+ BZS_EXT_RESIZE_STRING_BUFFER(destination_value, destination_length, exception);
278
+ if (exception != 0) {
279
+ return BZS_EXT_ERROR_ALLOCATE_FAILED;
280
+ }
281
+
282
+ return 0;
283
+ }
284
+
285
+ VALUE bzs_ext_decompress_string(VALUE BZS_EXT_UNUSED(self), VALUE source_value, VALUE options)
286
+ {
287
+ Check_Type(source_value, T_STRING);
288
+ Check_Type(options, T_HASH);
289
+ BZS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
290
+ BZS_EXT_GET_BOOL_OPTION(options, gvl);
291
+ BZS_EXT_RESOLVE_DECOMPRESSOR_OPTIONS(options);
292
+
293
+ bz_stream stream = {
294
+ .bzalloc = NULL,
295
+ .bzfree = NULL,
296
+ .opaque = NULL,
297
+ };
298
+
299
+ bzs_result_t result = BZ2_bzDecompressInit(&stream, verbosity, small);
300
+ if (result != BZ_OK) {
301
+ bzs_ext_raise_error(bzs_ext_get_error(result));
302
+ }
303
+
304
+ if (destination_buffer_length == 0) {
305
+ destination_buffer_length = BZS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR;
306
+ }
307
+
308
+ int exception;
309
+
310
+ BZS_EXT_CREATE_STRING_BUFFER(destination_value, destination_buffer_length, exception);
311
+ if (exception != 0) {
312
+ BZ2_bzDecompressEnd(&stream);
313
+ bzs_ext_raise_error(BZS_EXT_ERROR_ALLOCATE_FAILED);
314
+ }
315
+
316
+ const char* source = RSTRING_PTR(source_value);
317
+ size_t source_length = RSTRING_LEN(source_value);
318
+
319
+ bzs_ext_result_t ext_result =
320
+ decompress(&stream, source, source_length, destination_value, destination_buffer_length, gvl);
321
+
322
+ result = BZ2_bzDecompressEnd(&stream);
323
+ if (result != BZ_OK) {
324
+ ext_result = bzs_ext_get_error(result);
325
+ }
326
+
327
+ if (ext_result != 0) {
328
+ bzs_ext_raise_error(ext_result);
329
+ }
330
+
331
+ return destination_value;
332
+ }
333
+
334
+ // -- exports --
335
+
336
+ void bzs_ext_string_exports(VALUE root_module)
337
+ {
338
+ rb_define_module_function(root_module, "_native_compress_string", RUBY_METHOD_FUNC(bzs_ext_compress_string), 2);
339
+ rb_define_module_function(root_module, "_native_decompress_string", RUBY_METHOD_FUNC(bzs_ext_decompress_string), 2);
340
+ }
@@ -0,0 +1,14 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #if !defined(BZS_EXT_STRING_H)
5
+ #define BZS_EXT_STRING_H
6
+
7
+ #include "ruby.h"
8
+
9
+ VALUE bzs_ext_compress_string(VALUE self, VALUE source, VALUE options);
10
+ VALUE bzs_ext_decompress_string(VALUE self, VALUE source, VALUE options);
11
+
12
+ void bzs_ext_string_exports(VALUE root_module);
13
+
14
+ #endif // BZS_EXT_STRING_H
@@ -0,0 +1,15 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #include "utils.h"
5
+
6
+ #include <limits.h>
7
+
8
+ unsigned int bzs_consume_size(size_t size)
9
+ {
10
+ if (size > UINT_MAX) {
11
+ return UINT_MAX;
12
+ } else {
13
+ return (unsigned int) size;
14
+ }
15
+ }
@@ -0,0 +1,13 @@
1
+ // Ruby bindings for bzip2 library.
2
+ // Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ #if !defined(BZS_EXT_UTILS_H)
5
+ #define BZS_EXT_UTILS_H
6
+
7
+ #include <stdlib.h>
8
+
9
+ // Bzip2 size type may be limited to unsigned int.
10
+ // We need to prevent overflow by consuming max available unsigned int value.
11
+ unsigned int bzs_consume_size(size_t size);
12
+
13
+ #endif // BZS_EXT_UTILS_H
data/ext/extconf.rb ADDED
@@ -0,0 +1,94 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "mkmf"
5
+
6
+ have_func "rb_thread_call_without_gvl", "ruby/thread.h"
7
+
8
+ def require_header(name, constants: [], types: [])
9
+ abort "Can't find #{name} header" unless find_header name
10
+
11
+ constants.each do |constant|
12
+ abort "Can't find #{constant} constant in #{name} header" unless have_const constant, name
13
+ end
14
+
15
+ types.each do |type|
16
+ abort "Can't find #{type} type in #{name} header" unless find_type type, nil, name
17
+ end
18
+ end
19
+
20
+ require_header(
21
+ "bzlib.h",
22
+ :constants => %w[
23
+ BZ_RUN
24
+ BZ_RUN_OK
25
+ BZ_FINISH
26
+ BZ_FINISH_OK
27
+ BZ_FLUSH
28
+ BZ_FLUSH_OK
29
+ BZ_OK
30
+ BZ_PARAM_ERROR
31
+ BZ_STREAM_END
32
+ BZ_MEM_ERROR
33
+ BZ_DATA_ERROR
34
+ BZ_DATA_ERROR_MAGIC
35
+ BZ_UNEXPECTED_EOF
36
+ ],
37
+ :types => %w[
38
+ bz_stream
39
+ ]
40
+ )
41
+
42
+ def require_library(name, functions)
43
+ functions.each do |function|
44
+ abort "Can't find #{function} function in #{name} library" unless find_library name, function
45
+ end
46
+ end
47
+
48
+ require_library(
49
+ "bz2",
50
+ %w[
51
+ BZ2_bzCompressInit
52
+ BZ2_bzCompress
53
+ BZ2_bzCompressEnd
54
+ BZ2_bzDecompressInit
55
+ BZ2_bzDecompress
56
+ BZ2_bzDecompressEnd
57
+ BZ2_bzlibVersion
58
+ ]
59
+ )
60
+
61
+ extension_name = "bzs_ext".freeze
62
+ dir_config extension_name
63
+
64
+ # rubocop:disable Style/GlobalVars
65
+ $srcs = %w[
66
+ stream/compressor
67
+ stream/decompressor
68
+ buffer
69
+ error
70
+ io
71
+ main
72
+ option
73
+ string
74
+ utils
75
+ ]
76
+ .map { |name| "src/#{extension_name}/#{name}.c" }
77
+ .freeze
78
+
79
+ # Removing library duplicates.
80
+ $libs = $libs.split(%r{\s})
81
+ .reject(&:empty?)
82
+ .sort
83
+ .uniq
84
+ .join " "
85
+
86
+ if ENV["CI"]
87
+ $CFLAGS << " --coverage"
88
+ $LDFLAGS << " --coverage"
89
+ end
90
+
91
+ $VPATH << "$(srcdir)/#{extension_name}:$(srcdir)/#{extension_name}/stream"
92
+ # rubocop:enable Style/GlobalVars
93
+
94
+ create_makefile extension_name
data/lib/bzs/error.rb ADDED
@@ -0,0 +1,26 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "adsp"
5
+
6
+ module BZS
7
+ class BaseError < ::StandardError; end
8
+
9
+ class AllocateError < BaseError; end
10
+
11
+ class NotEnoughSourceBufferError < BaseError; end
12
+ class NotEnoughDestinationBufferError < BaseError; end
13
+ class DecompressorCorruptedSourceError < BaseError; end
14
+
15
+ class AccessIOError < BaseError; end
16
+ class ReadIOError < BaseError; end
17
+ class WriteIOError < BaseError; end
18
+
19
+ ValidateError = ADSP::ValidateError
20
+
21
+ NotEnoughDestinationError = ADSP::NotEnoughDestinationError
22
+ UsedAfterCloseError = ADSP::UsedAfterCloseError
23
+
24
+ NotImplementedError = ADSP::NotImplementedError
25
+ UnexpectedError = ADSP::UnexpectedError
26
+ end
data/lib/bzs/file.rb ADDED
@@ -0,0 +1,25 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "adsp/file"
5
+ require "bzs_ext"
6
+
7
+ require_relative "option"
8
+
9
+ module BZS
10
+ # BZS::File class.
11
+ class File < ADSP::File
12
+ # Current option class.
13
+ Option = BZS::Option
14
+
15
+ # Bypass native compress.
16
+ def self.native_compress_io(*args)
17
+ BZS._native_compress_io(*args)
18
+ end
19
+
20
+ # Bypass native decompress.
21
+ def self.native_decompress_io(*args)
22
+ BZS._native_decompress_io(*args)
23
+ end
24
+ end
25
+ end
data/lib/bzs/option.rb ADDED
@@ -0,0 +1,101 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "bzs_ext"
5
+
6
+ require_relative "error"
7
+ require_relative "validation"
8
+
9
+ module BZS
10
+ # BZS::Option module.
11
+ module Option
12
+ # Current default buffer length.
13
+ DEFAULT_BUFFER_LENGTH = 0
14
+
15
+ # Current compressor defaults.
16
+ COMPRESSOR_DEFAULTS = {
17
+ # Enables global VM lock where possible.
18
+ :gvl => false,
19
+ # Block size to be used for compression.
20
+ :block_size => nil,
21
+ # Controls threshold for switching from standard to fallback algorithm.
22
+ :work_factor => nil,
23
+ # Disables bzip2 library logging.
24
+ :quiet => nil
25
+ }
26
+ .freeze
27
+
28
+ # Current decompressor defaults.
29
+ DECOMPRESSOR_DEFAULTS = {
30
+ # Enables global VM lock where possible.
31
+ :gvl => false,
32
+ # Enables alternative decompression algorithm with less memory.
33
+ :small => nil,
34
+ # Disables bzip2 library logging.
35
+ :quiet => nil
36
+ }
37
+ .freeze
38
+
39
+ # Processes compressor +options+ and +buffer_length_names+.
40
+ # Option: +:source_buffer_length+ source buffer length.
41
+ # Option: +:destination_buffer_length+ destination buffer length.
42
+ # Option: +:gvl+ enables global VM lock where possible.
43
+ # Option: +:block_size+ block size to be used for compression.
44
+ # Option: +:work_factor+ controls threshold for switching from standard to fallback algorithm.
45
+ # Option: +:quiet+ disables bzip2 library logging.
46
+ # Returns processed compressor options.
47
+ def self.get_compressor_options(options, buffer_length_names)
48
+ Validation.validate_hash options
49
+
50
+ buffer_length_defaults = buffer_length_names.each_with_object({}) do |name, defaults|
51
+ defaults[name] = DEFAULT_BUFFER_LENGTH
52
+ end
53
+
54
+ options = COMPRESSOR_DEFAULTS.merge(buffer_length_defaults).merge options
55
+
56
+ buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
57
+
58
+ Validation.validate_bool options[:gvl]
59
+
60
+ block_size = options[:block_size]
61
+ Validation.validate_not_negative_integer block_size unless block_size.nil?
62
+
63
+ work_factor = options[:work_factor]
64
+ Validation.validate_not_negative_integer work_factor unless work_factor.nil?
65
+
66
+ quiet = options[:quiet]
67
+ Validation.validate_bool quiet unless quiet.nil?
68
+
69
+ options
70
+ end
71
+
72
+ # Processes decompressor +options+ and +buffer_length_names+.
73
+ # Option: +:source_buffer_length+ source buffer length.
74
+ # Option: +:destination_buffer_length+ destination buffer length.
75
+ # Option: +:gvl+ enables global VM lock where possible.
76
+ # Option: +:small+ enables alternative decompression algorithm with less memory.
77
+ # Option: +:quiet+ disables bzip2 library logging.
78
+ # Returns processed decompressor options.
79
+ def self.get_decompressor_options(options, buffer_length_names)
80
+ Validation.validate_hash options
81
+
82
+ buffer_length_defaults = buffer_length_names.each_with_object({}) do |name, defaults|
83
+ defaults[name] = DEFAULT_BUFFER_LENGTH
84
+ end
85
+
86
+ options = DECOMPRESSOR_DEFAULTS.merge(buffer_length_defaults).merge options
87
+
88
+ buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
89
+
90
+ Validation.validate_bool options[:gvl]
91
+
92
+ small = options[:small]
93
+ Validation.validate_bool small unless small.nil?
94
+
95
+ quiet = options[:quiet]
96
+ Validation.validate_bool quiet unless quiet.nil?
97
+
98
+ options
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,22 @@
1
+ # Ruby bindings for bzip2 library.
2
+ # Copyright (c) 2022 AUTHORS, MIT License.
3
+
4
+ require "adsp/stream/raw/compressor"
5
+ require "bzs_ext"
6
+
7
+ require_relative "../../option"
8
+
9
+ module BZS
10
+ module Stream
11
+ module Raw
12
+ # BZS::Stream::Raw::Compressor class.
13
+ class Compressor < ADSP::Stream::Raw::Compressor
14
+ # Current native compressor class.
15
+ NativeCompressor = Stream::NativeCompressor
16
+
17
+ # Current option class.
18
+ Option = BZS::Option
19
+ end
20
+ end
21
+ end
22
+ end