ruby-lzws 1.0.0 → 1.1.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.
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
+ }