ruby-lzws 1.1.7 → 1.4.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 +4 -4
- data/README.md +64 -30
- data/ext/extconf.rb +90 -20
- data/ext/lzws_ext/buffer.c +21 -9
- data/ext/lzws_ext/buffer.h +5 -5
- data/ext/lzws_ext/error.c +11 -13
- data/ext/lzws_ext/error.h +2 -1
- data/ext/lzws_ext/gvl.h +24 -0
- data/ext/lzws_ext/io.c +83 -20
- data/ext/lzws_ext/main.c +7 -1
- data/ext/lzws_ext/option.c +46 -11
- data/ext/lzws_ext/option.h +30 -24
- data/ext/lzws_ext/stream/compressor.c +84 -42
- data/ext/lzws_ext/stream/compressor.h +4 -1
- data/ext/lzws_ext/stream/decompressor.c +56 -31
- data/ext/lzws_ext/stream/decompressor.h +4 -1
- data/ext/lzws_ext/string.c +159 -93
- data/lib/lzws/file.rb +2 -2
- data/lib/lzws/option.rb +60 -31
- data/lib/lzws/stream/abstract.rb +5 -3
- data/lib/lzws/stream/reader.rb +3 -2
- data/lib/lzws/stream/reader_helpers.rb +1 -1
- data/lib/lzws/validation.rb +3 -1
- data/lib/lzws/version.rb +1 -1
- metadata +73 -16
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 "
|
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/
|
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
|
-
|
61
|
-
source_file
|
62
|
-
|
63
|
-
|
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
|
-
|
66
|
-
|
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
|
-
|
85
|
-
source_file
|
86
|
-
|
87
|
-
|
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
|
-
|
90
|
-
|
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
|
}
|
data/ext/lzws_ext/option.c
CHANGED
@@ -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
|
-
|
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
|
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
|
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
|
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
|
+
}
|
data/ext/lzws_ext/option.h
CHANGED
@@ -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
|
-
|
14
|
-
|
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
|
18
|
-
|
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
|
21
|
-
|
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
|
24
|
-
|
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
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
35
|
-
|
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
|
41
|
-
|
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
|
-
|
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(
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
size_t
|
101
|
-
|
102
|
-
|
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
|
-
|
125
|
+
Check_Type(source_value, T_STRING);
|
109
126
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
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
|
-
|
116
|
-
|
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
|
-
|
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
|
-
|
137
|
-
|
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
|
-
|
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 "
|
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);
|