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 +4 -4
- data/README.md +70 -69
- data/ext/extconf.rb +11 -2
- data/ext/lzws_ext/buffer.c +21 -7
- data/ext/lzws_ext/buffer.h +5 -5
- data/ext/lzws_ext/error.h +2 -1
- data/ext/lzws_ext/gvl.h +24 -0
- data/ext/lzws_ext/io.c +83 -19
- data/ext/lzws_ext/main.c +2 -0
- data/ext/lzws_ext/option.c +46 -10
- data/ext/lzws_ext/option.h +30 -24
- data/ext/lzws_ext/stream/compressor.c +84 -40
- data/ext/lzws_ext/stream/compressor.h +4 -1
- data/ext/lzws_ext/stream/decompressor.c +56 -29
- data/ext/lzws_ext/stream/decompressor.h +4 -1
- data/ext/lzws_ext/string.c +159 -92
- data/lib/lzws/file.rb +4 -0
- data/lib/lzws/option.rb +50 -27
- data/lib/lzws/stream/abstract.rb +1 -6
- data/lib/lzws/stream/raw/abstract.rb +4 -2
- data/lib/lzws/stream/raw/compressor.rb +2 -4
- data/lib/lzws/stream/raw/decompressor.rb +1 -3
- data/lib/lzws/stream/reader.rb +70 -51
- data/lib/lzws/stream/writer.rb +9 -4
- data/lib/lzws/stream/writer_helpers.rb +3 -2
- data/lib/lzws/validation.rb +1 -1
- data/lib/lzws/version.rb +1 -1
- metadata +21 -20
data/ext/lzws_ext/main.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include "lzws_ext/buffer.h"
|
5
5
|
#include "lzws_ext/io.h"
|
6
|
+
#include "lzws_ext/option.h"
|
6
7
|
#include "lzws_ext/stream/compressor.h"
|
7
8
|
#include "lzws_ext/stream/decompressor.h"
|
8
9
|
#include "lzws_ext/string.h"
|
@@ -14,6 +15,7 @@ void Init_lzws_ext()
|
|
14
15
|
|
15
16
|
lzws_ext_buffer_exports(root_module);
|
16
17
|
lzws_ext_io_exports(root_module);
|
18
|
+
lzws_ext_option_exports(root_module);
|
17
19
|
lzws_ext_compressor_exports(root_module);
|
18
20
|
lzws_ext_decompressor_exports(root_module);
|
19
21
|
lzws_ext_string_exports(root_module);
|
data/ext/lzws_ext/option.c
CHANGED
@@ -6,15 +6,15 @@
|
|
6
6
|
#include "lzws_ext/error.h"
|
7
7
|
#include "ruby.h"
|
8
8
|
|
9
|
-
|
9
|
+
// -- values --
|
10
|
+
|
11
|
+
static inline VALUE get_raw_value(VALUE options, const char* name)
|
10
12
|
{
|
11
13
|
return rb_funcall(options, rb_intern("[]"), 1, ID2SYM(rb_intern(name)));
|
12
14
|
}
|
13
15
|
|
14
|
-
bool
|
16
|
+
static inline bool get_bool_value(VALUE raw_value)
|
15
17
|
{
|
16
|
-
VALUE raw_value = get_raw_option_value(options, name);
|
17
|
-
|
18
18
|
int raw_type = TYPE(raw_value);
|
19
19
|
if (raw_type != T_TRUE && raw_type != T_FALSE) {
|
20
20
|
lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
|
@@ -23,20 +23,56 @@ bool lzws_ext_get_bool_option_value(VALUE options, const char* name)
|
|
23
23
|
return raw_type == T_TRUE;
|
24
24
|
}
|
25
25
|
|
26
|
-
unsigned int
|
26
|
+
static inline unsigned int get_uint_value(VALUE raw_value)
|
27
27
|
{
|
28
|
-
VALUE raw_value = get_raw_option_value(options, name);
|
29
|
-
|
30
28
|
Check_Type(raw_value, T_FIXNUM);
|
31
29
|
|
32
30
|
return NUM2UINT(raw_value);
|
33
31
|
}
|
34
32
|
|
35
|
-
size_t
|
33
|
+
static inline size_t get_size_value(VALUE raw_value)
|
36
34
|
{
|
37
|
-
VALUE raw_value = get_raw_option_value(options, name);
|
38
|
-
|
39
35
|
Check_Type(raw_value, T_FIXNUM);
|
40
36
|
|
41
37
|
return NUM2SIZET(raw_value);
|
42
38
|
}
|
39
|
+
|
40
|
+
void lzws_ext_resolve_bool_option(VALUE options, bool* option, const char* name)
|
41
|
+
{
|
42
|
+
VALUE raw_value = get_raw_value(options, name);
|
43
|
+
if (raw_value != Qnil) {
|
44
|
+
*option = get_bool_value(raw_value);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
void lzws_ext_resolve_max_code_bit_length_option(VALUE options, lzws_byte_fast_t* option, const char* name)
|
49
|
+
{
|
50
|
+
VALUE raw_value = get_raw_value(options, name);
|
51
|
+
if (raw_value != Qnil) {
|
52
|
+
*option = get_uint_value(raw_value);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
bool lzws_ext_get_bool_option_value(VALUE options, const char* name)
|
57
|
+
{
|
58
|
+
VALUE raw_value = get_raw_value(options, name);
|
59
|
+
|
60
|
+
return get_bool_value(raw_value);
|
61
|
+
}
|
62
|
+
|
63
|
+
size_t lzws_ext_get_size_option_value(VALUE options, const char* name)
|
64
|
+
{
|
65
|
+
VALUE raw_value = get_raw_value(options, name);
|
66
|
+
|
67
|
+
return get_size_value(raw_value);
|
68
|
+
}
|
69
|
+
|
70
|
+
// -- exports --
|
71
|
+
|
72
|
+
void lzws_ext_option_exports(VALUE root_module)
|
73
|
+
{
|
74
|
+
VALUE module = rb_define_module_under(root_module, "Option");
|
75
|
+
|
76
|
+
rb_define_const(module, "LOWEST_MAX_CODE_BIT_LENGTH", UINT2NUM(LZWS_LOWEST_MAX_CODE_BIT_LENGTH));
|
77
|
+
rb_define_const(module, "BIGGEST_MAX_CODE_BIT_LENGTH", UINT2NUM(LZWS_BIGGEST_MAX_CODE_BIT_LENGTH));
|
78
|
+
}
|
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,15 +4,16 @@
|
|
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
8
|
#include <lzws/compressor/state.h>
|
11
9
|
|
12
10
|
#include "lzws_ext/error.h"
|
11
|
+
#include "lzws_ext/gvl.h"
|
13
12
|
#include "lzws_ext/option.h"
|
14
13
|
#include "ruby.h"
|
15
14
|
|
15
|
+
// -- initialization --
|
16
|
+
|
16
17
|
static void free_compressor(lzws_ext_compressor_t* compressor_ptr)
|
17
18
|
{
|
18
19
|
lzws_compressor_state_t* state_ptr = compressor_ptr->state_ptr;
|
@@ -31,14 +32,14 @@ static void free_compressor(lzws_ext_compressor_t* compressor_ptr)
|
|
31
32
|
VALUE lzws_ext_allocate_compressor(VALUE klass)
|
32
33
|
{
|
33
34
|
lzws_ext_compressor_t* compressor_ptr;
|
34
|
-
|
35
|
-
VALUE self = Data_Make_Struct(klass, lzws_ext_compressor_t, NULL, free_compressor, compressor_ptr);
|
35
|
+
VALUE self = Data_Make_Struct(klass, lzws_ext_compressor_t, NULL, free_compressor, compressor_ptr);
|
36
36
|
|
37
37
|
compressor_ptr->state_ptr = NULL;
|
38
38
|
compressor_ptr->destination_buffer = NULL;
|
39
39
|
compressor_ptr->destination_buffer_length = 0;
|
40
40
|
compressor_ptr->remaining_destination_buffer = NULL;
|
41
41
|
compressor_ptr->remaining_destination_buffer_length = 0;
|
42
|
+
compressor_ptr->gvl = false;
|
42
43
|
|
43
44
|
return self;
|
44
45
|
}
|
@@ -51,15 +52,13 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
|
|
51
52
|
{
|
52
53
|
GET_COMPRESSOR(self);
|
53
54
|
Check_Type(options, T_HASH);
|
55
|
+
LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
56
|
+
LZWS_EXT_GET_BOOL_OPTION(options, gvl);
|
54
57
|
LZWS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
55
|
-
LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
56
58
|
|
57
59
|
lzws_compressor_state_t* state_ptr;
|
58
60
|
|
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
|
-
|
61
|
+
lzws_result_t result = lzws_compressor_get_initial_state(&state_ptr, &compressor_options);
|
63
62
|
if (result != 0) {
|
64
63
|
switch (result) {
|
65
64
|
case LZWS_COMPRESSOR_ALLOCATE_FAILED:
|
@@ -73,7 +72,9 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
|
|
73
72
|
|
74
73
|
lzws_ext_byte_t* destination_buffer;
|
75
74
|
|
76
|
-
result = lzws_create_destination_buffer_for_compressor(
|
75
|
+
result = lzws_create_destination_buffer_for_compressor(
|
76
|
+
&destination_buffer, &destination_buffer_length, compressor_options.quiet);
|
77
|
+
|
77
78
|
if (result != 0) {
|
78
79
|
lzws_compressor_free_state(state_ptr);
|
79
80
|
lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
|
@@ -84,66 +85,106 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
|
|
84
85
|
compressor_ptr->destination_buffer_length = destination_buffer_length;
|
85
86
|
compressor_ptr->remaining_destination_buffer = destination_buffer;
|
86
87
|
compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
88
|
+
compressor_ptr->gvl = gvl;
|
87
89
|
|
88
90
|
return Qnil;
|
89
91
|
}
|
90
92
|
|
93
|
+
// -- compress --
|
94
|
+
|
91
95
|
#define DO_NOT_USE_AFTER_CLOSE(compressor_ptr) \
|
92
96
|
if (compressor_ptr->state_ptr == NULL || compressor_ptr->destination_buffer == NULL) { \
|
93
97
|
lzws_ext_raise_error(LZWS_EXT_ERROR_USED_AFTER_CLOSE); \
|
94
98
|
}
|
95
99
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
size_t
|
101
|
-
|
102
|
-
|
100
|
+
typedef struct
|
101
|
+
{
|
102
|
+
lzws_ext_compressor_t* compressor_ptr;
|
103
|
+
lzws_ext_byte_t* remaining_source;
|
104
|
+
size_t* remaining_source_length_ptr;
|
105
|
+
lzws_result_t result;
|
106
|
+
} compress_args_t;
|
107
|
+
|
108
|
+
static inline void* compress_wrapper(void* data)
|
109
|
+
{
|
110
|
+
compress_args_t* args = data;
|
111
|
+
lzws_ext_compressor_t* compressor_ptr = args->compressor_ptr;
|
112
|
+
|
113
|
+
args->result = lzws_compress(
|
114
|
+
compressor_ptr->state_ptr,
|
115
|
+
&args->remaining_source,
|
116
|
+
args->remaining_source_length_ptr,
|
117
|
+
&compressor_ptr->remaining_destination_buffer,
|
118
|
+
&compressor_ptr->remaining_destination_buffer_length);
|
119
|
+
|
120
|
+
return NULL;
|
121
|
+
}
|
103
122
|
|
104
123
|
VALUE lzws_ext_compress(VALUE self, VALUE source_value)
|
105
124
|
{
|
106
125
|
GET_COMPRESSOR(self);
|
107
126
|
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
108
|
-
|
127
|
+
Check_Type(source_value, T_STRING);
|
109
128
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
129
|
+
const char* source = RSTRING_PTR(source_value);
|
130
|
+
size_t source_length = RSTRING_LEN(source_value);
|
131
|
+
lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*) source;
|
132
|
+
size_t remaining_source_length = source_length;
|
133
|
+
|
134
|
+
compress_args_t args = {
|
135
|
+
.compressor_ptr = compressor_ptr,
|
136
|
+
.remaining_source = remaining_source,
|
137
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
114
138
|
|
115
|
-
|
116
|
-
|
117
|
-
result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
|
139
|
+
LZWS_EXT_GVL_WRAP(compressor_ptr->gvl, compress_wrapper, &args);
|
140
|
+
if (args.result != 0 && args.result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
|
118
141
|
lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
|
119
142
|
}
|
120
143
|
|
121
144
|
VALUE bytes_written = SIZET2NUM(source_length - remaining_source_length);
|
122
|
-
VALUE needs_more_destination = result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
|
145
|
+
VALUE needs_more_destination = args.result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
|
123
146
|
|
124
147
|
return rb_ary_new_from_args(2, bytes_written, needs_more_destination);
|
125
148
|
}
|
126
149
|
|
150
|
+
// -- compressor finish --
|
151
|
+
|
152
|
+
typedef struct
|
153
|
+
{
|
154
|
+
lzws_ext_compressor_t* compressor_ptr;
|
155
|
+
lzws_result_t result;
|
156
|
+
} compressor_finish_args_t;
|
157
|
+
|
158
|
+
static inline void* compressor_finish_wrapper(void* data)
|
159
|
+
{
|
160
|
+
compressor_finish_args_t* args = data;
|
161
|
+
lzws_ext_compressor_t* compressor_ptr = args->compressor_ptr;
|
162
|
+
|
163
|
+
args->result = lzws_compressor_finish(
|
164
|
+
compressor_ptr->state_ptr,
|
165
|
+
&compressor_ptr->remaining_destination_buffer,
|
166
|
+
&compressor_ptr->remaining_destination_buffer_length);
|
167
|
+
|
168
|
+
return NULL;
|
169
|
+
}
|
170
|
+
|
127
171
|
VALUE lzws_ext_compressor_finish(VALUE self)
|
128
172
|
{
|
129
173
|
GET_COMPRESSOR(self);
|
130
174
|
DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
|
131
175
|
|
132
|
-
|
133
|
-
compressor_ptr->state_ptr,
|
134
|
-
&compressor_ptr->remaining_destination_buffer, &compressor_ptr->remaining_destination_buffer_length);
|
176
|
+
compressor_finish_args_t args = {.compressor_ptr = compressor_ptr};
|
135
177
|
|
136
|
-
|
137
|
-
|
138
|
-
result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
|
178
|
+
LZWS_EXT_GVL_WRAP(compressor_ptr->gvl, compressor_finish_wrapper, &args);
|
179
|
+
if (args.result != 0 && args.result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
|
139
180
|
lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
|
140
181
|
}
|
141
182
|
|
142
|
-
|
143
|
-
|
144
|
-
return needs_more_destination;
|
183
|
+
return args.result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
|
145
184
|
}
|
146
185
|
|
186
|
+
// -- other --
|
187
|
+
|
147
188
|
VALUE lzws_ext_compressor_read_result(VALUE self)
|
148
189
|
{
|
149
190
|
GET_COMPRESSOR(self);
|
@@ -153,10 +194,9 @@ VALUE lzws_ext_compressor_read_result(VALUE self)
|
|
153
194
|
size_t destination_buffer_length = compressor_ptr->destination_buffer_length;
|
154
195
|
size_t remaining_destination_buffer_length = compressor_ptr->remaining_destination_buffer_length;
|
155
196
|
|
156
|
-
const char* result = (const char*)destination_buffer;
|
197
|
+
const char* result = (const char*) destination_buffer;
|
157
198
|
size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
|
158
|
-
|
159
|
-
VALUE result_value = rb_str_new(result, result_length);
|
199
|
+
VALUE result_value = rb_str_new(result, result_length);
|
160
200
|
|
161
201
|
compressor_ptr->remaining_destination_buffer = destination_buffer;
|
162
202
|
compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
@@ -164,6 +204,8 @@ VALUE lzws_ext_compressor_read_result(VALUE self)
|
|
164
204
|
return result_value;
|
165
205
|
}
|
166
206
|
|
207
|
+
// -- cleanup --
|
208
|
+
|
167
209
|
VALUE lzws_ext_compressor_close(VALUE self)
|
168
210
|
{
|
169
211
|
GET_COMPRESSOR(self);
|
@@ -183,12 +225,14 @@ VALUE lzws_ext_compressor_close(VALUE self)
|
|
183
225
|
compressor_ptr->destination_buffer = NULL;
|
184
226
|
}
|
185
227
|
|
186
|
-
// It is possible to keep "destination_buffer_length", "remaining_destination_buffer"
|
187
|
-
// and "
|
228
|
+
// It is possible to keep "destination_buffer_length", "remaining_destination_buffer",
|
229
|
+
// "remaining_destination_buffer_length" and "gvl" as is.
|
188
230
|
|
189
231
|
return Qnil;
|
190
232
|
}
|
191
233
|
|
234
|
+
// -- exports --
|
235
|
+
|
192
236
|
void lzws_ext_compressor_exports(VALUE root_module)
|
193
237
|
{
|
194
238
|
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);
|
@@ -4,15 +4,16 @@
|
|
4
4
|
#include "lzws_ext/stream/decompressor.h"
|
5
5
|
|
6
6
|
#include <lzws/buffer.h>
|
7
|
-
#include <lzws/common.h>
|
8
|
-
#include <lzws/decompressor/common.h>
|
9
7
|
#include <lzws/decompressor/main.h>
|
10
8
|
#include <lzws/decompressor/state.h>
|
11
9
|
|
12
10
|
#include "lzws_ext/error.h"
|
11
|
+
#include "lzws_ext/gvl.h"
|
13
12
|
#include "lzws_ext/option.h"
|
14
13
|
#include "ruby.h"
|
15
14
|
|
15
|
+
// -- initialization --
|
16
|
+
|
16
17
|
static void free_decompressor(lzws_ext_decompressor_t* decompressor_ptr)
|
17
18
|
{
|
18
19
|
lzws_decompressor_state_t* state_ptr = decompressor_ptr->state_ptr;
|
@@ -31,7 +32,6 @@ static void free_decompressor(lzws_ext_decompressor_t* decompressor_ptr)
|
|
31
32
|
VALUE lzws_ext_allocate_decompressor(VALUE klass)
|
32
33
|
{
|
33
34
|
lzws_ext_decompressor_t* decompressor_ptr;
|
34
|
-
|
35
35
|
VALUE self = Data_Make_Struct(klass, lzws_ext_decompressor_t, NULL, free_decompressor, decompressor_ptr);
|
36
36
|
|
37
37
|
decompressor_ptr->state_ptr = NULL;
|
@@ -51,15 +51,13 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
51
51
|
{
|
52
52
|
GET_DECOMPRESSOR(self);
|
53
53
|
Check_Type(options, T_HASH);
|
54
|
+
LZWS_EXT_GET_SIZE_OPTION(options, destination_buffer_length);
|
55
|
+
LZWS_EXT_GET_BOOL_OPTION(options, gvl);
|
54
56
|
LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
55
|
-
LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
|
56
57
|
|
57
58
|
lzws_decompressor_state_t* state_ptr;
|
58
59
|
|
59
|
-
lzws_result_t result = lzws_decompressor_get_initial_state(
|
60
|
-
&state_ptr,
|
61
|
-
without_magic_header, msb, unaligned_bit_groups, quiet);
|
62
|
-
|
60
|
+
lzws_result_t result = lzws_decompressor_get_initial_state(&state_ptr, &decompressor_options);
|
63
61
|
if (result != 0) {
|
64
62
|
switch (result) {
|
65
63
|
case LZWS_DECOMPRESSOR_ALLOCATE_FAILED:
|
@@ -71,7 +69,9 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
71
69
|
|
72
70
|
lzws_ext_byte_t* destination_buffer;
|
73
71
|
|
74
|
-
result = lzws_create_destination_buffer_for_decompressor(
|
72
|
+
result = lzws_create_destination_buffer_for_decompressor(
|
73
|
+
&destination_buffer, &destination_buffer_length, decompressor_options.quiet);
|
74
|
+
|
75
75
|
if (result != 0) {
|
76
76
|
lzws_decompressor_free_state(state_ptr);
|
77
77
|
lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
|
@@ -82,38 +82,60 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
|
|
82
82
|
decompressor_ptr->destination_buffer_length = destination_buffer_length;
|
83
83
|
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
84
84
|
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
85
|
+
decompressor_ptr->gvl = gvl;
|
85
86
|
|
86
87
|
return Qnil;
|
87
88
|
}
|
88
89
|
|
90
|
+
// -- decompress --
|
91
|
+
|
89
92
|
#define DO_NOT_USE_AFTER_CLOSE(decompressor_ptr) \
|
90
93
|
if (decompressor_ptr->state_ptr == NULL || decompressor_ptr->destination_buffer == NULL) { \
|
91
94
|
lzws_ext_raise_error(LZWS_EXT_ERROR_USED_AFTER_CLOSE); \
|
92
95
|
}
|
93
96
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
size_t
|
99
|
-
|
100
|
-
|
97
|
+
typedef struct
|
98
|
+
{
|
99
|
+
lzws_ext_decompressor_t* decompressor_ptr;
|
100
|
+
lzws_ext_byte_t* remaining_source;
|
101
|
+
size_t* remaining_source_length_ptr;
|
102
|
+
lzws_result_t result;
|
103
|
+
} decompress_args_t;
|
104
|
+
|
105
|
+
static inline void* decompress_wrapper(void* data)
|
106
|
+
{
|
107
|
+
decompress_args_t* args = data;
|
108
|
+
lzws_ext_decompressor_t* decompressor_ptr = args->decompressor_ptr;
|
109
|
+
|
110
|
+
args->result = lzws_decompress(
|
111
|
+
decompressor_ptr->state_ptr,
|
112
|
+
&args->remaining_source,
|
113
|
+
args->remaining_source_length_ptr,
|
114
|
+
&decompressor_ptr->remaining_destination_buffer,
|
115
|
+
&decompressor_ptr->remaining_destination_buffer_length);
|
116
|
+
|
117
|
+
return NULL;
|
118
|
+
}
|
101
119
|
|
102
120
|
VALUE lzws_ext_decompress(VALUE self, VALUE source_value)
|
103
121
|
{
|
104
122
|
GET_DECOMPRESSOR(self);
|
105
123
|
DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
|
106
|
-
|
124
|
+
Check_Type(source_value, T_STRING);
|
107
125
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
126
|
+
const char* source = RSTRING_PTR(source_value);
|
127
|
+
size_t source_length = RSTRING_LEN(source_value);
|
128
|
+
lzws_ext_byte_t* remaining_source = (lzws_ext_byte_t*) source;
|
129
|
+
size_t remaining_source_length = source_length;
|
112
130
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
131
|
+
decompress_args_t args = {
|
132
|
+
.decompressor_ptr = decompressor_ptr,
|
133
|
+
.remaining_source = remaining_source,
|
134
|
+
.remaining_source_length_ptr = &remaining_source_length};
|
135
|
+
|
136
|
+
LZWS_EXT_GVL_WRAP(decompressor_ptr->gvl, decompress_wrapper, &args);
|
137
|
+
if (args.result != 0 && args.result != LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
|
138
|
+
switch (args.result) {
|
117
139
|
case LZWS_DECOMPRESSOR_INVALID_MAGIC_HEADER:
|
118
140
|
case LZWS_DECOMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH:
|
119
141
|
lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
|
@@ -125,11 +147,13 @@ VALUE lzws_ext_decompress(VALUE self, VALUE source_value)
|
|
125
147
|
}
|
126
148
|
|
127
149
|
VALUE bytes_read = SIZET2NUM(source_length - remaining_source_length);
|
128
|
-
VALUE needs_more_destination = result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
|
150
|
+
VALUE needs_more_destination = args.result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
|
129
151
|
|
130
152
|
return rb_ary_new_from_args(2, bytes_read, needs_more_destination);
|
131
153
|
}
|
132
154
|
|
155
|
+
// -- other --
|
156
|
+
|
133
157
|
VALUE lzws_ext_decompressor_read_result(VALUE self)
|
134
158
|
{
|
135
159
|
GET_DECOMPRESSOR(self);
|
@@ -139,10 +163,9 @@ VALUE lzws_ext_decompressor_read_result(VALUE self)
|
|
139
163
|
size_t destination_buffer_length = decompressor_ptr->destination_buffer_length;
|
140
164
|
size_t remaining_destination_buffer_length = decompressor_ptr->remaining_destination_buffer_length;
|
141
165
|
|
142
|
-
const char* result = (const char*)destination_buffer;
|
166
|
+
const char* result = (const char*) destination_buffer;
|
143
167
|
size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
|
144
|
-
|
145
|
-
VALUE result_value = rb_str_new(result, result_length);
|
168
|
+
VALUE result_value = rb_str_new(result, result_length);
|
146
169
|
|
147
170
|
decompressor_ptr->remaining_destination_buffer = destination_buffer;
|
148
171
|
decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
|
@@ -150,6 +173,8 @@ VALUE lzws_ext_decompressor_read_result(VALUE self)
|
|
150
173
|
return result_value;
|
151
174
|
}
|
152
175
|
|
176
|
+
// -- cleanup --
|
177
|
+
|
153
178
|
VALUE lzws_ext_decompressor_close(VALUE self)
|
154
179
|
{
|
155
180
|
GET_DECOMPRESSOR(self);
|
@@ -175,6 +200,8 @@ VALUE lzws_ext_decompressor_close(VALUE self)
|
|
175
200
|
return Qnil;
|
176
201
|
}
|
177
202
|
|
203
|
+
// -- exports --
|
204
|
+
|
178
205
|
void lzws_ext_decompressor_exports(VALUE root_module)
|
179
206
|
{
|
180
207
|
VALUE module = rb_define_module_under(root_module, "Stream");
|