ruby-lzws 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/lzws_ext/main.c CHANGED
@@ -1,42 +1,21 @@
1
1
  // Ruby bindings for lzws library.
2
2
  // Copyright (c) 2019 AUTHORS, MIT License.
3
3
 
4
- #include "ruby.h"
5
-
4
+ #include "lzws_ext/buffer.h"
6
5
  #include "lzws_ext/common.h"
7
6
  #include "lzws_ext/io.h"
8
7
  #include "lzws_ext/stream/compressor.h"
9
8
  #include "lzws_ext/stream/decompressor.h"
10
9
  #include "lzws_ext/string.h"
10
+ #include "ruby.h"
11
11
 
12
12
  void Init_lzws_ext()
13
13
  {
14
- VALUE root = rb_define_module(LZWS_EXT_MODULE_NAME);
15
-
16
- // It is better to use these functions internally and prepare pretty wrappers for public usage.
17
- rb_define_module_function(root, "_native_compress_io", RUBY_METHOD_FUNC(lzws_ext_compress_io), 3);
18
- rb_define_module_function(root, "_native_decompress_io", RUBY_METHOD_FUNC(lzws_ext_decompress_io), 3);
19
- rb_define_module_function(root, "_native_compress_string", RUBY_METHOD_FUNC(lzws_ext_compress_string), 2);
20
- rb_define_module_function(root, "_native_decompress_string", RUBY_METHOD_FUNC(lzws_ext_decompress_string), 2);
21
-
22
- // -----
23
-
24
- VALUE stream = rb_define_module_under(root, "Stream");
25
-
26
- VALUE compressor = rb_define_class_under(stream, "NativeCompressor", rb_cObject);
27
- rb_define_alloc_func(compressor, lzws_ext_allocate_compressor);
28
- rb_define_method(compressor, "initialize", lzws_ext_initialize_compressor, 1);
29
- rb_define_method(compressor, "write_magic_header", lzws_ext_compressor_write_magic_header, 0);
30
- rb_define_method(compressor, "write", lzws_ext_compress, 1);
31
- rb_define_method(compressor, "flush", lzws_ext_flush_compressor, 0);
32
- rb_define_method(compressor, "read_result", lzws_ext_compressor_read_result, 0);
33
- rb_define_method(compressor, "close", lzws_ext_compressor_close, 0);
14
+ VALUE root_module = rb_define_module(LZWS_EXT_MODULE_NAME);
34
15
 
35
- VALUE decompressor = rb_define_class_under(stream, "NativeDecompressor", rb_cObject);
36
- rb_define_alloc_func(decompressor, lzws_ext_allocate_decompressor);
37
- rb_define_method(decompressor, "initialize", lzws_ext_initialize_decompressor, 1);
38
- rb_define_method(decompressor, "read_magic_header", lzws_ext_decompressor_read_magic_header, 1);
39
- rb_define_method(decompressor, "read", lzws_ext_decompress, 1);
40
- rb_define_method(decompressor, "read_result", lzws_ext_decompressor_read_result, 0);
41
- rb_define_method(decompressor, "close", lzws_ext_decompressor_close, 0);
16
+ lzws_ext_buffer_exports(root_module);
17
+ lzws_ext_io_exports(root_module);
18
+ lzws_ext_compressor_exports(root_module);
19
+ lzws_ext_decompressor_exports(root_module);
20
+ lzws_ext_string_exports(root_module);
42
21
  }
@@ -1,22 +1,35 @@
1
1
  // Ruby bindings for lzws library.
2
2
  // Copyright (c) 2019 AUTHORS, MIT License.
3
3
 
4
- #include "ruby.h"
5
-
6
4
  #include "lzws_ext/option.h"
7
5
 
8
- VALUE lzws_ext_get_option(VALUE options, const char* name)
6
+ #include <stdbool.h>
7
+
8
+ #include "lzws_ext/error.h"
9
+ #include "ruby.h"
10
+
11
+ static inline VALUE get_raw_option_value(VALUE options, const char* name)
9
12
  {
10
- VALUE name_symbol = ID2SYM(rb_intern(name));
11
- return rb_funcall(options, rb_intern("[]"), 1, name_symbol);
13
+ return rb_funcall(options, rb_intern("[]"), 1, ID2SYM(rb_intern(name)));
12
14
  }
13
15
 
14
- void lzws_ext_check_bool_type(VALUE option, const char* name)
16
+ bool lzws_ext_get_bool_option_value(VALUE options, const char* name)
15
17
  {
16
- int type = TYPE(option);
18
+ VALUE raw_value = get_raw_option_value(options, name);
17
19
 
18
- if (type != T_TRUE && type != T_FALSE) {
19
- VALUE message = rb_sprintf("wrong value for \"%s\" (expected true or false)", name);
20
- rb_exc_raise(rb_exc_new_str(rb_eFatal, message));
20
+ int raw_type = TYPE(raw_value);
21
+ if (raw_type != T_TRUE && raw_type != T_FALSE) {
22
+ lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
21
23
  }
24
+
25
+ return raw_type == T_TRUE;
26
+ }
27
+
28
+ unsigned long lzws_ext_get_fixnum_option_value(VALUE options, const char* name)
29
+ {
30
+ VALUE raw_value = get_raw_option_value(options, name);
31
+
32
+ Check_Type(raw_value, T_FIXNUM);
33
+
34
+ return NUM2UINT(raw_value);
22
35
  }
@@ -4,57 +4,34 @@
4
4
  #if !defined(LZWS_EXT_OPTIONS_H)
5
5
  #define LZWS_EXT_OPTIONS_H
6
6
 
7
+ #include <stdbool.h>
8
+
7
9
  #include "ruby.h"
8
10
 
9
- VALUE lzws_ext_get_option(VALUE options, const char* name);
10
- void lzws_ext_check_bool_type(VALUE option, const char* name);
11
-
12
- #define LZWS_EXT_GET_COMPRESSOR_OPTIONS(options) \
13
- Check_Type(options, T_HASH); \
14
- \
15
- VALUE buffer_length_value = lzws_ext_get_option(options, "buffer_length"); \
16
- VALUE without_magic_header_value = lzws_ext_get_option(options, "without_magic_header"); \
17
- VALUE max_code_bit_length_value = lzws_ext_get_option(options, "max_code_bit_length"); \
18
- VALUE block_mode_value = lzws_ext_get_option(options, "block_mode"); \
19
- VALUE msb_value = lzws_ext_get_option(options, "msb"); \
20
- VALUE unaligned_bit_groups_value = lzws_ext_get_option(options, "unaligned_bit_groups"); \
21
- VALUE quiet_value = lzws_ext_get_option(options, "quiet"); \
22
- \
23
- Check_Type(buffer_length_value, T_FIXNUM); \
24
- lzws_ext_check_bool_type(without_magic_header_value, "without_magic_header"); \
25
- Check_Type(max_code_bit_length_value, T_FIXNUM); \
26
- lzws_ext_check_bool_type(block_mode_value, "block_mode"); \
27
- lzws_ext_check_bool_type(msb_value, "msb"); \
28
- lzws_ext_check_bool_type(unaligned_bit_groups_value, "unaligned_bit_groups"); \
29
- lzws_ext_check_bool_type(quiet_value, "quiet"); \
30
- \
31
- size_t buffer_length = rb_num2uint(buffer_length_value); \
32
- bool without_magic_header = TYPE(without_magic_header_value) == T_TRUE; \
33
- uint_fast8_t max_code_bit_length = rb_num2uint(max_code_bit_length_value); \
34
- bool block_mode = TYPE(block_mode_value) == T_TRUE; \
35
- bool msb = TYPE(msb_value) == T_TRUE; \
36
- bool unaligned_bit_groups = TYPE(unaligned_bit_groups_value) == T_TRUE; \
37
- bool quiet = TYPE(quiet_value) == T_TRUE;
38
-
39
- #define LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options) \
40
- Check_Type(options, T_HASH); \
41
- \
42
- VALUE buffer_length_value = lzws_ext_get_option(options, "buffer_length"); \
43
- VALUE without_magic_header_value = lzws_ext_get_option(options, "without_magic_header"); \
44
- VALUE msb_value = lzws_ext_get_option(options, "msb"); \
45
- VALUE unaligned_bit_groups_value = lzws_ext_get_option(options, "unaligned_bit_groups"); \
46
- VALUE quiet_value = lzws_ext_get_option(options, "quiet"); \
47
- \
48
- Check_Type(buffer_length_value, T_FIXNUM); \
49
- lzws_ext_check_bool_type(without_magic_header_value, "without_magic_header"); \
50
- lzws_ext_check_bool_type(msb_value, "msb"); \
51
- lzws_ext_check_bool_type(unaligned_bit_groups_value, "unaligned_bit_groups"); \
52
- lzws_ext_check_bool_type(quiet_value, "quiet"); \
53
- \
54
- size_t buffer_length = rb_num2uint(buffer_length_value); \
55
- bool without_magic_header = TYPE(without_magic_header_value) == T_TRUE; \
56
- bool msb = TYPE(msb_value) == T_TRUE; \
57
- bool unaligned_bit_groups = TYPE(unaligned_bit_groups_value) == T_TRUE; \
58
- bool quiet = TYPE(quiet_value) == T_TRUE;
11
+ bool lzws_ext_get_bool_option_value(VALUE options, const char* name);
12
+ unsigned long lzws_ext_get_fixnum_option_value(VALUE options, const char* name);
13
+
14
+ #define LZWS_EXT_GET_BOOL_OPTION(options, name) \
15
+ bool name = lzws_ext_get_bool_option_value(options, #name);
16
+
17
+ #define LZWS_EXT_GET_FIXNUM_OPTION(options, type, name) \
18
+ type name = lzws_ext_get_fixnum_option_value(options, #name);
19
+
20
+ #define LZWS_EXT_GET_COMPRESSOR_OPTIONS(options) \
21
+ LZWS_EXT_GET_BOOL_OPTION(options, without_magic_header); \
22
+ LZWS_EXT_GET_FIXNUM_OPTION(options, uint_fast8_t, max_code_bit_length); \
23
+ LZWS_EXT_GET_BOOL_OPTION(options, block_mode); \
24
+ LZWS_EXT_GET_BOOL_OPTION(options, msb); \
25
+ LZWS_EXT_GET_BOOL_OPTION(options, unaligned_bit_groups); \
26
+ LZWS_EXT_GET_BOOL_OPTION(options, quiet);
27
+
28
+ #define LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options) \
29
+ LZWS_EXT_GET_BOOL_OPTION(options, without_magic_header); \
30
+ LZWS_EXT_GET_BOOL_OPTION(options, msb); \
31
+ LZWS_EXT_GET_BOOL_OPTION(options, unaligned_bit_groups); \
32
+ LZWS_EXT_GET_BOOL_OPTION(options, quiet);
33
+
34
+ #define LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, name) \
35
+ LZWS_EXT_GET_FIXNUM_OPTION(options, size_t, name);
59
36
 
60
37
  #endif // LZWS_EXT_OPTIONS_H
@@ -1,18 +1,18 @@
1
1
  // Ruby bindings for lzws library.
2
2
  // Copyright (c) 2019 AUTHORS, MIT License.
3
3
 
4
+ #include "lzws_ext/stream/compressor.h"
5
+
4
6
  #include <lzws/buffer.h>
5
7
  #include <lzws/compressor/common.h>
6
- #include <lzws/compressor/header.h>
7
8
  #include <lzws/compressor/main.h>
8
9
  #include <lzws/compressor/state.h>
9
-
10
- #include "ruby.h"
10
+ #include <stdint.h>
11
+ #include <stdlib.h>
11
12
 
12
13
  #include "lzws_ext/error.h"
13
- #include "lzws_ext/macro.h"
14
14
  #include "lzws_ext/option.h"
15
- #include "lzws_ext/stream/compressor.h"
15
+ #include "ruby.h"
16
16
 
17
17
  static void free_compressor(lzws_ext_compressor_t* compressor_ptr)
18
18
  {
@@ -51,37 +51,36 @@ VALUE lzws_ext_allocate_compressor(VALUE klass)
51
51
  VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
52
52
  {
53
53
  GET_COMPRESSOR(self);
54
+ Check_Type(options, T_HASH);
54
55
  LZWS_EXT_GET_COMPRESSOR_OPTIONS(options);
55
- LZWS_EXT_UNUSED_VARIABLE(without_magic_header);
56
+ LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
56
57
 
57
- lzws_compressor_state_t* compressor_state_ptr;
58
+ lzws_compressor_state_t* state_ptr;
58
59
 
59
60
  lzws_result_t result = lzws_compressor_get_initial_state(
60
- &compressor_state_ptr,
61
- max_code_bit_length, block_mode, msb, unaligned_bit_groups, quiet);
61
+ &state_ptr,
62
+ without_magic_header, max_code_bit_length, block_mode, msb, unaligned_bit_groups, quiet);
62
63
 
63
- if (result == LZWS_COMPRESSOR_ALLOCATE_FAILED) {
64
- lzws_ext_raise_error("AllocateError", "allocate error");
65
- }
66
- else if (result == LZWS_COMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH) {
67
- lzws_ext_raise_error("ValidateError", "validate error");
68
- }
69
- else if (result != 0) {
70
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
64
+ if (result != 0) {
65
+ switch (result) {
66
+ case LZWS_COMPRESSOR_ALLOCATE_FAILED:
67
+ lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
68
+ case LZWS_COMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH:
69
+ lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
70
+ default:
71
+ lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
72
+ }
71
73
  }
72
74
 
73
- compressor_ptr->state_ptr = compressor_state_ptr;
74
-
75
- // -----
76
-
77
75
  uint8_t* destination_buffer;
78
- size_t destination_buffer_length = buffer_length;
79
76
 
80
- result = lzws_create_buffer_for_compressor(&destination_buffer, &destination_buffer_length, quiet);
77
+ result = lzws_create_destination_buffer_for_compressor(&destination_buffer, &destination_buffer_length, quiet);
81
78
  if (result != 0) {
82
- lzws_ext_raise_error("AllocateError", "allocate error");
79
+ lzws_compressor_free_state(state_ptr);
80
+ lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
83
81
  }
84
82
 
83
+ compressor_ptr->state_ptr = state_ptr;
85
84
  compressor_ptr->destination_buffer = destination_buffer;
86
85
  compressor_ptr->destination_buffer_length = destination_buffer_length;
87
86
  compressor_ptr->remaining_destination_buffer = destination_buffer;
@@ -92,83 +91,58 @@ VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options)
92
91
 
93
92
  #define DO_NOT_USE_AFTER_CLOSE(compressor_ptr) \
94
93
  if (compressor_ptr->state_ptr == NULL || compressor_ptr->destination_buffer == NULL) { \
95
- lzws_ext_raise_error("UsedAfterCloseError", "compressor used after closed"); \
94
+ lzws_ext_raise_error(LZWS_EXT_ERROR_USED_AFTER_CLOSE); \
96
95
  }
97
96
 
98
- VALUE lzws_ext_compressor_write_magic_header(VALUE self)
99
- {
100
- GET_COMPRESSOR(self);
101
- DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
102
-
103
- lzws_result_t result = lzws_compressor_write_magic_header(
104
- &compressor_ptr->remaining_destination_buffer,
105
- &compressor_ptr->remaining_destination_buffer_length);
97
+ #define GET_SOURCE_DATA(source_value) \
98
+ Check_Type(source_value, T_STRING); \
99
+ \
100
+ const char* source = RSTRING_PTR(source_value); \
101
+ size_t source_length = RSTRING_LEN(source_value); \
102
+ uint8_t* remaining_source = (uint8_t*)source; \
103
+ size_t remaining_source_length = source_length;
106
104
 
107
- if (result == 0) {
108
- return Qfalse;
109
- }
110
- else if (result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
111
- return Qtrue;
112
- }
113
- else {
114
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
115
- }
116
- }
117
-
118
- #define GET_STRING(source) \
119
- Check_Type(source, T_STRING); \
120
- \
121
- const char* source_data = RSTRING_PTR(source); \
122
- size_t source_length = RSTRING_LEN(source);
123
-
124
- VALUE lzws_ext_compress(VALUE self, VALUE source)
105
+ VALUE lzws_ext_compress(VALUE self, VALUE source_value)
125
106
  {
126
107
  GET_COMPRESSOR(self);
127
108
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
128
- GET_STRING(source);
129
-
130
- uint8_t* remaining_source_data = (uint8_t*)source_data;
131
- size_t remaining_source_length = source_length;
109
+ GET_SOURCE_DATA(source_value);
132
110
 
133
111
  lzws_result_t result = lzws_compress(
134
112
  compressor_ptr->state_ptr,
135
- &remaining_source_data,
136
- &remaining_source_length,
137
- &compressor_ptr->remaining_destination_buffer,
138
- &compressor_ptr->remaining_destination_buffer_length);
113
+ &remaining_source, &remaining_source_length,
114
+ &compressor_ptr->remaining_destination_buffer, &compressor_ptr->remaining_destination_buffer_length);
139
115
 
140
- VALUE bytes_written = INT2NUM(source_length - remaining_source_length);
141
-
142
- if (result == LZWS_COMPRESSOR_NEEDS_MORE_SOURCE) {
143
- return rb_ary_new_from_args(2, bytes_written, Qfalse);
144
- }
145
- else if (result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
146
- return rb_ary_new_from_args(2, bytes_written, Qtrue);
147
- }
148
- else {
149
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
116
+ if (
117
+ result != 0 &&
118
+ result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
119
+ lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
150
120
  }
121
+
122
+ VALUE bytes_written = UINT2NUM(source_length - remaining_source_length);
123
+ VALUE needs_more_destination = result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
124
+
125
+ return rb_ary_new_from_args(2, bytes_written, needs_more_destination);
151
126
  }
152
127
 
153
- VALUE lzws_ext_flush_compressor(VALUE self)
128
+ VALUE lzws_ext_compressor_finish(VALUE self)
154
129
  {
155
130
  GET_COMPRESSOR(self);
156
131
  DO_NOT_USE_AFTER_CLOSE(compressor_ptr);
157
132
 
158
- lzws_result_t result = lzws_flush_compressor(
133
+ lzws_result_t result = lzws_compressor_finish(
159
134
  compressor_ptr->state_ptr,
160
- &compressor_ptr->remaining_destination_buffer,
161
- &compressor_ptr->remaining_destination_buffer_length);
135
+ &compressor_ptr->remaining_destination_buffer, &compressor_ptr->remaining_destination_buffer_length);
162
136
 
163
- if (result == 0) {
164
- return Qfalse;
165
- }
166
- else if (result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
167
- return Qtrue;
168
- }
169
- else {
170
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
137
+ if (
138
+ result != 0 &&
139
+ result != LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION) {
140
+ lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
171
141
  }
142
+
143
+ VALUE needs_more_destination = result == LZWS_COMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
144
+
145
+ return needs_more_destination;
172
146
  }
173
147
 
174
148
  VALUE lzws_ext_compressor_read_result(VALUE self)
@@ -180,15 +154,15 @@ VALUE lzws_ext_compressor_read_result(VALUE self)
180
154
  size_t destination_buffer_length = compressor_ptr->destination_buffer_length;
181
155
  size_t remaining_destination_buffer_length = compressor_ptr->remaining_destination_buffer_length;
182
156
 
183
- const char* result_data = (const char*)destination_buffer;
157
+ const char* result = (const char*)destination_buffer;
184
158
  size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
185
159
 
186
- VALUE result = rb_str_new(result_data, result_length);
160
+ VALUE result_value = rb_str_new(result, result_length);
187
161
 
188
162
  compressor_ptr->remaining_destination_buffer = destination_buffer;
189
163
  compressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
190
164
 
191
- return result;
165
+ return result_value;
192
166
  }
193
167
 
194
168
  VALUE lzws_ext_compressor_close(VALUE self)
@@ -215,3 +189,16 @@ VALUE lzws_ext_compressor_close(VALUE self)
215
189
 
216
190
  return Qnil;
217
191
  }
192
+
193
+ void lzws_ext_compressor_exports(VALUE root_module)
194
+ {
195
+ VALUE stream = rb_define_module_under(root_module, "Stream");
196
+
197
+ VALUE compressor = rb_define_class_under(stream, "NativeCompressor", rb_cObject);
198
+ rb_define_alloc_func(compressor, lzws_ext_allocate_compressor);
199
+ rb_define_method(compressor, "initialize", lzws_ext_initialize_compressor, 1);
200
+ rb_define_method(compressor, "write", lzws_ext_compress, 1);
201
+ rb_define_method(compressor, "finish", lzws_ext_compressor_finish, 0);
202
+ rb_define_method(compressor, "read_result", lzws_ext_compressor_read_result, 0);
203
+ rb_define_method(compressor, "close", lzws_ext_compressor_close, 0);
204
+ }
@@ -5,6 +5,8 @@
5
5
  #define LZWS_EXT_STREAM_COMPRESSOR_H
6
6
 
7
7
  #include <lzws/compressor/state.h>
8
+ #include <stdint.h>
9
+ #include <stdlib.h>
8
10
 
9
11
  #include "ruby.h"
10
12
 
@@ -18,10 +20,11 @@ typedef struct {
18
20
 
19
21
  VALUE lzws_ext_allocate_compressor(VALUE klass);
20
22
  VALUE lzws_ext_initialize_compressor(VALUE self, VALUE options);
21
- VALUE lzws_ext_compressor_write_magic_header(VALUE self);
22
23
  VALUE lzws_ext_compress(VALUE self, VALUE source);
23
- VALUE lzws_ext_flush_compressor(VALUE self);
24
+ VALUE lzws_ext_compressor_finish(VALUE self);
24
25
  VALUE lzws_ext_compressor_read_result(VALUE self);
25
26
  VALUE lzws_ext_compressor_close(VALUE self);
26
27
 
28
+ void lzws_ext_compressor_exports(VALUE root_module);
29
+
27
30
  #endif // LZWS_EXT_STREAM_COMPRESSOR_H
@@ -1,18 +1,18 @@
1
1
  // Ruby bindings for lzws library.
2
2
  // Copyright (c) 2019 AUTHORS, MIT License.
3
3
 
4
+ #include "lzws_ext/stream/decompressor.h"
5
+
4
6
  #include <lzws/buffer.h>
5
7
  #include <lzws/decompressor/common.h>
6
- #include <lzws/decompressor/header.h>
7
8
  #include <lzws/decompressor/main.h>
8
9
  #include <lzws/decompressor/state.h>
9
-
10
- #include "ruby.h"
10
+ #include <stdint.h>
11
+ #include <stdlib.h>
11
12
 
12
13
  #include "lzws_ext/error.h"
13
- #include "lzws_ext/macro.h"
14
14
  #include "lzws_ext/option.h"
15
- #include "lzws_ext/stream/decompressor.h"
15
+ #include "ruby.h"
16
16
 
17
17
  static void free_decompressor(lzws_ext_decompressor_t* decompressor_ptr)
18
18
  {
@@ -51,34 +51,34 @@ VALUE lzws_ext_allocate_decompressor(VALUE klass)
51
51
  VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
52
52
  {
53
53
  GET_DECOMPRESSOR(self);
54
+ Check_Type(options, T_HASH);
54
55
  LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
55
- LZWS_EXT_UNUSED_VARIABLE(without_magic_header);
56
+ LZWS_EXT_GET_BUFFER_LENGTH_OPTION(options, destination_buffer_length);
56
57
 
57
- lzws_decompressor_state_t* decompressor_state_ptr;
58
+ lzws_decompressor_state_t* state_ptr;
58
59
 
59
60
  lzws_result_t result = lzws_decompressor_get_initial_state(
60
- &decompressor_state_ptr,
61
- msb, unaligned_bit_groups, quiet);
61
+ &state_ptr,
62
+ without_magic_header, msb, unaligned_bit_groups, quiet);
62
63
 
63
- if (result == LZWS_DECOMPRESSOR_ALLOCATE_FAILED) {
64
- lzws_ext_raise_error("AllocateError", "allocate error");
65
- }
66
- else if (result != 0) {
67
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
64
+ if (result != 0) {
65
+ switch (result) {
66
+ case LZWS_DECOMPRESSOR_ALLOCATE_FAILED:
67
+ lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
68
+ default:
69
+ lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
70
+ }
68
71
  }
69
72
 
70
- decompressor_ptr->state_ptr = decompressor_state_ptr;
71
-
72
- // -----
73
-
74
73
  uint8_t* destination_buffer;
75
- size_t destination_buffer_length = buffer_length;
76
74
 
77
- result = lzws_create_buffer_for_decompressor(&destination_buffer, &destination_buffer_length, quiet);
75
+ result = lzws_create_destination_buffer_for_decompressor(&destination_buffer, &destination_buffer_length, quiet);
78
76
  if (result != 0) {
79
- lzws_ext_raise_error("AllocateError", "allocate error");
77
+ lzws_decompressor_free_state(state_ptr);
78
+ lzws_ext_raise_error(LZWS_EXT_ERROR_ALLOCATE_FAILED);
80
79
  }
81
80
 
81
+ decompressor_ptr->state_ptr = state_ptr;
82
82
  decompressor_ptr->destination_buffer = destination_buffer;
83
83
  decompressor_ptr->destination_buffer_length = destination_buffer_length;
84
84
  decompressor_ptr->remaining_destination_buffer = destination_buffer;
@@ -87,77 +87,48 @@ VALUE lzws_ext_initialize_decompressor(VALUE self, VALUE options)
87
87
  return Qnil;
88
88
  }
89
89
 
90
- #define GET_STRING(source) \
91
- Check_Type(source, T_STRING); \
92
- \
93
- const char* source_data = RSTRING_PTR(source); \
94
- size_t source_length = RSTRING_LEN(source);
95
-
96
90
  #define DO_NOT_USE_AFTER_CLOSE(decompressor_ptr) \
97
91
  if (decompressor_ptr->state_ptr == NULL || decompressor_ptr->destination_buffer == NULL) { \
98
- lzws_ext_raise_error("UsedAfterCloseError", "decompressor used after close"); \
92
+ lzws_ext_raise_error(LZWS_EXT_ERROR_USED_AFTER_CLOSE); \
99
93
  }
100
94
 
101
- VALUE lzws_ext_decompressor_read_magic_header(VALUE self, VALUE source)
102
- {
103
- GET_DECOMPRESSOR(self);
104
- DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
105
- GET_STRING(source);
106
-
107
- uint8_t* remaining_source_data = (uint8_t*)source_data;
108
- size_t remaining_source_length = source_length;
109
-
110
- lzws_result_t result = lzws_decompressor_read_magic_header(
111
- decompressor_ptr->state_ptr,
112
- &remaining_source_data,
113
- &remaining_source_length);
95
+ #define GET_SOURCE_DATA(source_value) \
96
+ Check_Type(source_value, T_STRING); \
97
+ \
98
+ const char* source = RSTRING_PTR(source_value); \
99
+ size_t source_length = RSTRING_LEN(source_value); \
100
+ uint8_t* remaining_source = (uint8_t*)source; \
101
+ size_t remaining_source_length = source_length;
114
102
 
115
- VALUE bytes_read = INT2NUM(source_length - remaining_source_length);
116
-
117
- if (result == 0 || result == LZWS_DECOMPRESSOR_NEEDS_MORE_SOURCE) {
118
- return bytes_read;
119
- }
120
- else if (result == LZWS_DECOMPRESSOR_INVALID_MAGIC_HEADER) {
121
- lzws_ext_raise_error("ValidateError", "validate error");
122
- }
123
- else {
124
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
125
- }
126
- }
127
-
128
- VALUE lzws_ext_decompress(VALUE self, VALUE source)
103
+ VALUE lzws_ext_decompress(VALUE self, VALUE source_value)
129
104
  {
130
105
  GET_DECOMPRESSOR(self);
131
106
  DO_NOT_USE_AFTER_CLOSE(decompressor_ptr);
132
- GET_STRING(source);
133
-
134
- uint8_t* remaining_source_data = (uint8_t*)source_data;
135
- size_t remaining_source_length = source_length;
107
+ GET_SOURCE_DATA(source_value);
136
108
 
137
109
  lzws_result_t result = lzws_decompress(
138
110
  decompressor_ptr->state_ptr,
139
- &remaining_source_data,
140
- &remaining_source_length,
141
- &decompressor_ptr->remaining_destination_buffer,
142
- &decompressor_ptr->remaining_destination_buffer_length);
143
-
144
- VALUE bytes_read = INT2NUM(source_length - remaining_source_length);
145
-
146
- if (result == LZWS_DECOMPRESSOR_NEEDS_MORE_SOURCE) {
147
- return rb_ary_new_from_args(2, bytes_read, Qfalse);
148
- }
149
- else if (result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
150
- return rb_ary_new_from_args(2, bytes_read, Qtrue);
151
- }
152
- else if (result == LZWS_DECOMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH) {
153
- lzws_ext_raise_error("ValidateError", "validate error");
154
- }
155
- else if (result == LZWS_DECOMPRESSOR_CORRUPTED_SOURCE) {
156
- lzws_ext_raise_error("DecompressorCorruptedSourceError", "decompressor received corrupted source");
157
- }
158
- else {
159
- lzws_ext_raise_error("UnexpectedError", "unexpected error");
160
- }
111
+ &remaining_source, &remaining_source_length,
112
+ &decompressor_ptr->remaining_destination_buffer, &decompressor_ptr->remaining_destination_buffer_length);
113
+
114
+ if (
115
+ result != 0 &&
116
+ result != LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION) {
117
+ switch (result) {
118
+ case LZWS_DECOMPRESSOR_INVALID_MAGIC_HEADER:
119
+ case LZWS_DECOMPRESSOR_INVALID_MAX_CODE_BIT_LENGTH:
120
+ lzws_ext_raise_error(LZWS_EXT_ERROR_VALIDATE_FAILED);
121
+ case LZWS_DECOMPRESSOR_CORRUPTED_SOURCE:
122
+ lzws_ext_raise_error(LZWS_EXT_ERROR_DECOMPRESSOR_CORRUPTED_SOURCE);
123
+ default:
124
+ lzws_ext_raise_error(LZWS_EXT_ERROR_UNEXPECTED);
125
+ }
126
+ }
127
+
128
+ VALUE bytes_read = UINT2NUM(source_length - remaining_source_length);
129
+ VALUE needs_more_destination = result == LZWS_DECOMPRESSOR_NEEDS_MORE_DESTINATION ? Qtrue : Qfalse;
130
+
131
+ return rb_ary_new_from_args(2, bytes_read, needs_more_destination);
161
132
  }
162
133
 
163
134
  VALUE lzws_ext_decompressor_read_result(VALUE self)
@@ -169,15 +140,15 @@ VALUE lzws_ext_decompressor_read_result(VALUE self)
169
140
  size_t destination_buffer_length = decompressor_ptr->destination_buffer_length;
170
141
  size_t remaining_destination_buffer_length = decompressor_ptr->remaining_destination_buffer_length;
171
142
 
172
- const char* result_data = (const char*)destination_buffer;
143
+ const char* result = (const char*)destination_buffer;
173
144
  size_t result_length = destination_buffer_length - remaining_destination_buffer_length;
174
145
 
175
- VALUE result = rb_str_new(result_data, result_length);
146
+ VALUE result_value = rb_str_new(result, result_length);
176
147
 
177
148
  decompressor_ptr->remaining_destination_buffer = destination_buffer;
178
149
  decompressor_ptr->remaining_destination_buffer_length = destination_buffer_length;
179
150
 
180
- return result;
151
+ return result_value;
181
152
  }
182
153
 
183
154
  VALUE lzws_ext_decompressor_close(VALUE self)
@@ -204,3 +175,15 @@ VALUE lzws_ext_decompressor_close(VALUE self)
204
175
 
205
176
  return Qnil;
206
177
  }
178
+
179
+ void lzws_ext_decompressor_exports(VALUE root_module)
180
+ {
181
+ VALUE stream = rb_define_module_under(root_module, "Stream");
182
+
183
+ VALUE decompressor = rb_define_class_under(stream, "NativeDecompressor", rb_cObject);
184
+ rb_define_alloc_func(decompressor, lzws_ext_allocate_decompressor);
185
+ rb_define_method(decompressor, "initialize", lzws_ext_initialize_decompressor, 1);
186
+ rb_define_method(decompressor, "read", lzws_ext_decompress, 1);
187
+ rb_define_method(decompressor, "read_result", lzws_ext_decompressor_read_result, 0);
188
+ rb_define_method(decompressor, "close", lzws_ext_decompressor_close, 0);
189
+ }