ruby-lzws 1.0.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 +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +21 -0
- data/README.md +188 -0
- data/ext/extconf.rb +77 -0
- data/ext/lzws_ext/common.h +9 -0
- data/ext/lzws_ext/error.c +14 -0
- data/ext/lzws_ext/error.h +11 -0
- data/ext/lzws_ext/io.c +92 -0
- data/ext/lzws_ext/io.h +12 -0
- data/ext/lzws_ext/macro.h +15 -0
- data/ext/lzws_ext/main.c +42 -0
- data/ext/lzws_ext/option.c +22 -0
- data/ext/lzws_ext/option.h +60 -0
- data/ext/lzws_ext/stream/compressor.c +217 -0
- data/ext/lzws_ext/stream/compressor.h +27 -0
- data/ext/lzws_ext/stream/decompressor.c +206 -0
- data/ext/lzws_ext/stream/decompressor.h +26 -0
- data/ext/lzws_ext/string.c +78 -0
- data/ext/lzws_ext/string.h +12 -0
- data/lib/lzws/error.rb +20 -0
- data/lib/lzws/file.rb +56 -0
- data/lib/lzws/option.rb +66 -0
- data/lib/lzws/stream/abstract.rb +153 -0
- data/lib/lzws/stream/delegates.rb +36 -0
- data/lib/lzws/stream/raw/abstract.rb +46 -0
- data/lib/lzws/stream/raw/compressor.rb +100 -0
- data/lib/lzws/stream/raw/decompressor.rb +78 -0
- data/lib/lzws/stream/reader.rb +163 -0
- data/lib/lzws/stream/reader_helpers.rb +192 -0
- data/lib/lzws/stream/stat.rb +78 -0
- data/lib/lzws/stream/writer.rb +145 -0
- data/lib/lzws/stream/writer_helpers.rb +93 -0
- data/lib/lzws/string.rb +27 -0
- data/lib/lzws/validation.rb +36 -0
- data/lib/lzws/version.rb +6 -0
- data/lib/lzws.rb +4 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5e42a999e18187b07931b4c7127274339f8d6eb61490d2c3bcd504180c674d43
|
4
|
+
data.tar.gz: 8516d4a94686aeeb2587fcb6bd862dc85ff651ac6e71ae0449e3797a85653f78
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4c8f80f27ac4b2e12bc3628468b94bbebe5b00b688a6dc586013797b5eabb8a1a85da39fdd2ba5d48ed81d71d77df463800f6ef8c285d41bf057c1d306ed2727
|
7
|
+
data.tar.gz: f4ced4337b346873836d004c57ca6411f62ba604d32a69001658db3705c4098f1a938e23c2242092bd76e645792824daeba93680ea3d3da5c4529872279095cc
|
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Andrew Aladjev
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 AUTHORS
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
# Ruby bindings for lzws library
|
2
|
+
|
3
|
+
[](https://travis-ci.org/andrew-aladev/ruby-lzws)
|
4
|
+
[](https://ci.appveyor.com/project/andrew-aladev/ruby-lzws/branch/master)
|
5
|
+
|
6
|
+
See [lzws library](https://github.com/andrew-aladev/lzws).
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Please install lzws library first.
|
11
|
+
|
12
|
+
```sh
|
13
|
+
gem install ruby-lzws
|
14
|
+
```
|
15
|
+
|
16
|
+
You can build it from source.
|
17
|
+
|
18
|
+
```sh
|
19
|
+
rake gem
|
20
|
+
gem install pkg/ruby-lzws-*.gem
|
21
|
+
```
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
There are simple APIs: `String` and `File`. Also you can use generic streaming API: `Stream::Writer` and `Stream::Reader`.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require "lzws"
|
29
|
+
|
30
|
+
data = LZWS::String.compress "TOBEORNOTTOBEORTOBEORNOT"
|
31
|
+
puts LZWS::String.decompress(data)
|
32
|
+
|
33
|
+
LZWS::File.compress "file.txt", "file.txt.Z"
|
34
|
+
LZWS::File.decompress "file.txt.Z", "file.txt"
|
35
|
+
|
36
|
+
LZWS::Stream::Writer.open("file.txt.Z") { |writer| writer << "TOBEORNOTTOBEORTOBEORNOT" }
|
37
|
+
puts LZWS::Stream::Reader.open("file.txt.Z") { |reader| reader.read }
|
38
|
+
```
|
39
|
+
|
40
|
+
You can create and read `tar.Z` archives with `minitar` for example.
|
41
|
+
LZWS is fully compatible with UNIX compress (with default options).
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require "lzws"
|
45
|
+
require "minitar"
|
46
|
+
|
47
|
+
LZWS::Stream::Writer.open "file.tar.Z" do |writer|
|
48
|
+
Minitar::Writer.open writer do |tar|
|
49
|
+
tar.add_file_simple "file", :data => "TOBEORNOTTOBEORTOBEORNOT"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
LZWS::Stream::Reader.open "file.tar.Z" do |reader|
|
54
|
+
Minitar::Reader.open reader do |tar|
|
55
|
+
tar.each_entry do |entry|
|
56
|
+
puts entry.name
|
57
|
+
puts entry.read
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
Each API supports additional options, please read lzws docs for more info.
|
64
|
+
|
65
|
+
Compressor:
|
66
|
+
|
67
|
+
```
|
68
|
+
:max_code_bit_length
|
69
|
+
:block_mode
|
70
|
+
:buffer_length
|
71
|
+
:without_magic_header
|
72
|
+
:msb
|
73
|
+
:unaligned_bit_groups
|
74
|
+
:quiet
|
75
|
+
```
|
76
|
+
|
77
|
+
Decompressor:
|
78
|
+
|
79
|
+
```
|
80
|
+
:buffer_length
|
81
|
+
:without_magic_header
|
82
|
+
:msb
|
83
|
+
:unaligned_bit_groups
|
84
|
+
:quiet
|
85
|
+
```
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
require "lzws"
|
89
|
+
|
90
|
+
data = LZWS::String.compress "TOBEORNOTTOBEORTOBEORNOT", :msb => true
|
91
|
+
puts LZWS::String.decompress(data, :msb => true)
|
92
|
+
```
|
93
|
+
|
94
|
+
You can use `Content-Encoding: compress`.
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
require "lzws"
|
98
|
+
require "sinatra"
|
99
|
+
|
100
|
+
get "/" do
|
101
|
+
headers["Content-Encoding"] = "compress"
|
102
|
+
LZWS::String.compress "TOBEORNOTTOBEORTOBEORNOT"
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
## Docs
|
107
|
+
|
108
|
+
`LZWS::String`:
|
109
|
+
|
110
|
+
```
|
111
|
+
::compress(source, options = {})
|
112
|
+
::decompress(source, options = {})
|
113
|
+
```
|
114
|
+
|
115
|
+
`LZWS::File`:
|
116
|
+
|
117
|
+
```
|
118
|
+
::compress(source, destination, options = {})
|
119
|
+
::decompress(source, destination, options = {})
|
120
|
+
```
|
121
|
+
|
122
|
+
`LZWS::Stream::Writer` and `LZWS::Stream::Reader`:
|
123
|
+
|
124
|
+
```
|
125
|
+
::open(file_path, options = {}, :external_encoding => nil, :internal_encoding => nil, &block)
|
126
|
+
#io
|
127
|
+
#stat
|
128
|
+
#external_encoding
|
129
|
+
#internal_encoding
|
130
|
+
#pos
|
131
|
+
#tell
|
132
|
+
#advise
|
133
|
+
#set_encoding(external_encoding, internal_encoding, transcode_options)
|
134
|
+
#rewind
|
135
|
+
#close
|
136
|
+
#closed?
|
137
|
+
#to_io
|
138
|
+
```
|
139
|
+
|
140
|
+
`Stream::Writer`:
|
141
|
+
|
142
|
+
```
|
143
|
+
::new(destination_io, options = {}, :external_encoding => nil)
|
144
|
+
#write(*objects)
|
145
|
+
#flush
|
146
|
+
#write_nonblock(object, *options)
|
147
|
+
#flush_nonblock(*options)
|
148
|
+
#rewind_nonblock(*options)
|
149
|
+
#close_nonblock(*options)
|
150
|
+
#<<(object)
|
151
|
+
#print(*objects)
|
152
|
+
#printf(*args)
|
153
|
+
#putc(object, encoding: ::Encoding::BINARY)
|
154
|
+
#puts(*objects)
|
155
|
+
```
|
156
|
+
|
157
|
+
`Stream::Reader`:
|
158
|
+
|
159
|
+
```
|
160
|
+
::new(source_io, options = {}, :external_encoding => nil, :internal_encoding => nil)
|
161
|
+
#lineno
|
162
|
+
#lineno=
|
163
|
+
#read(bytes_to_read = nil, out_buffer = nil)
|
164
|
+
#readpartial(bytes_to_read = nil, out_buffer = nil)
|
165
|
+
#read_nonblock(bytes_to_read, out_buffer = nil, *options)
|
166
|
+
#eof?
|
167
|
+
#getbyte
|
168
|
+
#each_byte(&block)
|
169
|
+
#readbyte
|
170
|
+
#ungetbyte(byte)
|
171
|
+
#getc
|
172
|
+
#readchar
|
173
|
+
#each_char(&block)
|
174
|
+
#ungetc(char)
|
175
|
+
#gets(separator = $OUTPUT_RECORD_SEPARATOR, limit = nil)
|
176
|
+
#readline
|
177
|
+
#readlines
|
178
|
+
#each(&block)
|
179
|
+
#each_line(&block)
|
180
|
+
#ungetline(line)
|
181
|
+
```
|
182
|
+
|
183
|
+
`LZWS::Stream::Writer` and `LZWS::Stream::Reader` behaviour is the same as builtin [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.6.3/libdoc/zlib/rdoc/Zlib/GzipReader.html), [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.6.3/libdoc/zlib/rdoc/Zlib/GzipWriter.html) and [`IO`](https://ruby-doc.org/core-2.6.3/IO.html).
|
184
|
+
Please read these method descriptions in ruby doc.
|
185
|
+
|
186
|
+
## License
|
187
|
+
|
188
|
+
MIT license, see LICENSE and AUTHORS.
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Ruby bindings for lzws library.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "mkmf"
|
5
|
+
|
6
|
+
def require_header(name)
|
7
|
+
abort "Can't find #{name} header" unless find_header name
|
8
|
+
end
|
9
|
+
|
10
|
+
require_header "lzws/buffer.h"
|
11
|
+
require_header "lzws/compressor/common.h"
|
12
|
+
require_header "lzws/compressor/header.h"
|
13
|
+
require_header "lzws/compressor/main.h"
|
14
|
+
require_header "lzws/compressor/state.h"
|
15
|
+
require_header "lzws/decompressor/common.h"
|
16
|
+
require_header "lzws/decompressor/header.h"
|
17
|
+
require_header "lzws/decompressor/main.h"
|
18
|
+
require_header "lzws/decompressor/state.h"
|
19
|
+
require_header "lzws/file.h"
|
20
|
+
require_header "lzws/string.h"
|
21
|
+
|
22
|
+
def require_library(name, functions)
|
23
|
+
functions.each do |function|
|
24
|
+
abort "Can't find #{name} library and #{function} function" unless find_library name, function
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
functions = %w[
|
29
|
+
lzws_create_buffer_for_compressor
|
30
|
+
lzws_create_buffer_for_decompressor
|
31
|
+
lzws_resize_buffer
|
32
|
+
|
33
|
+
lzws_compress_string
|
34
|
+
lzws_decompress_string
|
35
|
+
|
36
|
+
lzws_compress_file
|
37
|
+
lzws_decompress_file
|
38
|
+
|
39
|
+
lzws_compressor_write_magic_header
|
40
|
+
lzws_compressor_get_initial_state
|
41
|
+
lzws_compress
|
42
|
+
lzws_flush_compressor
|
43
|
+
lzws_compressor_free_state
|
44
|
+
|
45
|
+
lzws_decompressor_read_magic_header
|
46
|
+
lzws_decompressor_get_initial_state
|
47
|
+
lzws_decompress
|
48
|
+
lzws_decompressor_free_state
|
49
|
+
]
|
50
|
+
.freeze
|
51
|
+
|
52
|
+
require_library "lzws", functions
|
53
|
+
|
54
|
+
extension_name = "lzws_ext".freeze
|
55
|
+
dir_config extension_name
|
56
|
+
|
57
|
+
sources = %w[
|
58
|
+
stream/compressor
|
59
|
+
stream/decompressor
|
60
|
+
error
|
61
|
+
io
|
62
|
+
main
|
63
|
+
option
|
64
|
+
string
|
65
|
+
]
|
66
|
+
.freeze
|
67
|
+
|
68
|
+
# rubocop:disable Style/GlobalVars
|
69
|
+
$srcs = sources
|
70
|
+
.map { |name| "src/#{extension_name}/#{name}.c" }
|
71
|
+
.freeze
|
72
|
+
|
73
|
+
$CFLAGS << " -Wno-declaration-after-statement"
|
74
|
+
$VPATH << "$(srcdir)/#{extension_name}:$(srcdir)/#{extension_name}/stream"
|
75
|
+
# rubocop:enable Style/GlobalVars
|
76
|
+
|
77
|
+
create_makefile extension_name
|
@@ -0,0 +1,14 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
#include "lzws_ext/common.h"
|
7
|
+
#include "lzws_ext/error.h"
|
8
|
+
|
9
|
+
void lzws_ext_raise_error(const char* name, const char* description)
|
10
|
+
{
|
11
|
+
VALUE module = rb_define_module(LZWS_EXT_MODULE_NAME);
|
12
|
+
VALUE error = rb_const_get(module, rb_intern(name));
|
13
|
+
rb_raise(error, "%s", description);
|
14
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#if !defined(LZWS_EXT_ERROR_H)
|
5
|
+
#define LZWS_EXT_ERROR_H
|
6
|
+
|
7
|
+
#include "ruby.h"
|
8
|
+
|
9
|
+
NORETURN(void lzws_ext_raise_error(const char* name, const char* description));
|
10
|
+
|
11
|
+
#endif // LZWS_EXT_ERROR_H
|
data/ext/lzws_ext/io.c
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#include <lzws/file.h>
|
5
|
+
|
6
|
+
#include "ruby.h"
|
7
|
+
#include "ruby/io.h"
|
8
|
+
|
9
|
+
#include "lzws_ext/error.h"
|
10
|
+
#include "lzws_ext/io.h"
|
11
|
+
#include "lzws_ext/macro.h"
|
12
|
+
#include "lzws_ext/option.h"
|
13
|
+
|
14
|
+
#define GET_FILE(target) \
|
15
|
+
Check_Type(target, T_FILE); \
|
16
|
+
\
|
17
|
+
rb_io_t *target##_io; \
|
18
|
+
GetOpenFile(target, target##_io); \
|
19
|
+
\
|
20
|
+
FILE *target##_file = rb_io_stdio_file(target##_io); \
|
21
|
+
if (target##_file == NULL) { \
|
22
|
+
lzws_ext_raise_error("AccessIOError", "failed to access IO"); \
|
23
|
+
}
|
24
|
+
|
25
|
+
VALUE lzws_ext_compress_io(VALUE LZWS_EXT_UNUSED(self), VALUE source, VALUE destination, VALUE options)
|
26
|
+
{
|
27
|
+
GET_FILE(source);
|
28
|
+
GET_FILE(destination);
|
29
|
+
LZWS_EXT_GET_COMPRESSOR_OPTIONS(options);
|
30
|
+
|
31
|
+
lzws_result_t result = lzws_compress_file(
|
32
|
+
source_file, buffer_length,
|
33
|
+
destination_file, buffer_length,
|
34
|
+
without_magic_header, max_code_bit_length, block_mode, msb, unaligned_bit_groups, quiet);
|
35
|
+
|
36
|
+
if (result == LZWS_FILE_ALLOCATE_FAILED) {
|
37
|
+
lzws_ext_raise_error("AllocateError", "allocate error");
|
38
|
+
}
|
39
|
+
else if (result == LZWS_FILE_VALIDATE_FAILED) {
|
40
|
+
lzws_ext_raise_error("ValidateError", "validate error");
|
41
|
+
}
|
42
|
+
else if (result == LZWS_FILE_READ_FAILED) {
|
43
|
+
lzws_ext_raise_error("ReadIOError", "failed to read IO");
|
44
|
+
}
|
45
|
+
else if (result == LZWS_FILE_WRITE_FAILED) {
|
46
|
+
lzws_ext_raise_error("WriteIOError", "failed to write IO");
|
47
|
+
}
|
48
|
+
else if (result != 0) {
|
49
|
+
lzws_ext_raise_error("UnexpectedError", "unexpected error");
|
50
|
+
}
|
51
|
+
|
52
|
+
// Ruby itself won't flush stdio file before closing fd, flush is required.
|
53
|
+
fflush(destination_file);
|
54
|
+
|
55
|
+
return Qnil;
|
56
|
+
}
|
57
|
+
|
58
|
+
VALUE lzws_ext_decompress_io(VALUE LZWS_EXT_UNUSED(self), VALUE source, VALUE destination, VALUE options)
|
59
|
+
{
|
60
|
+
GET_FILE(source);
|
61
|
+
GET_FILE(destination);
|
62
|
+
LZWS_EXT_GET_DECOMPRESSOR_OPTIONS(options);
|
63
|
+
|
64
|
+
lzws_result_t result = lzws_decompress_file(
|
65
|
+
source_file, buffer_length,
|
66
|
+
destination_file, buffer_length,
|
67
|
+
without_magic_header, msb, unaligned_bit_groups, quiet);
|
68
|
+
|
69
|
+
if (result == LZWS_FILE_ALLOCATE_FAILED) {
|
70
|
+
lzws_ext_raise_error("AllocateError", "allocate error");
|
71
|
+
}
|
72
|
+
else if (result == LZWS_FILE_VALIDATE_FAILED) {
|
73
|
+
lzws_ext_raise_error("ValidateError", "validate error");
|
74
|
+
}
|
75
|
+
else if (result == LZWS_FILE_DECOMPRESSOR_CORRUPTED_SOURCE) {
|
76
|
+
lzws_ext_raise_error("DecompressorCorruptedSourceError", "decompressor received corrupted source");
|
77
|
+
}
|
78
|
+
else if (result == LZWS_FILE_READ_FAILED) {
|
79
|
+
lzws_ext_raise_error("ReadIOError", "failed to read IO");
|
80
|
+
}
|
81
|
+
else if (result == LZWS_FILE_WRITE_FAILED) {
|
82
|
+
lzws_ext_raise_error("WriteIOError", "failed to write IO");
|
83
|
+
}
|
84
|
+
else if (result != 0) {
|
85
|
+
lzws_ext_raise_error("UnexpectedError", "unexpected error");
|
86
|
+
}
|
87
|
+
|
88
|
+
// Ruby itself won't flush stdio file before closing fd, flush is required.
|
89
|
+
fflush(destination_file);
|
90
|
+
|
91
|
+
return Qnil;
|
92
|
+
}
|
data/ext/lzws_ext/io.h
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#if !defined(LZWS_EXT_IO_H)
|
5
|
+
#define LZWS_EXT_IO_H
|
6
|
+
|
7
|
+
#include "ruby.h"
|
8
|
+
|
9
|
+
VALUE lzws_ext_compress_io(VALUE self, VALUE source, VALUE destination, VALUE options);
|
10
|
+
VALUE lzws_ext_decompress_io(VALUE self, VALUE source, VALUE destination, VALUE options);
|
11
|
+
|
12
|
+
#endif // LZWS_EXT_IO_H
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#if !defined(LZWS_EXT_MACRO_H)
|
5
|
+
#define LZWS_EXT_MACRO_H
|
6
|
+
|
7
|
+
#if defined(__GNUC__)
|
8
|
+
#define LZWS_EXT_UNUSED(x) x __attribute__((__unused__))
|
9
|
+
#else
|
10
|
+
#define LZWS_EXT_UNUSED(x) x
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#define LZWS_EXT_UNUSED_VARIABLE(x) (void)(x)
|
14
|
+
|
15
|
+
#endif // LZWS_EXT_MACRO_H
|
data/ext/lzws_ext/main.c
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
#include "lzws_ext/common.h"
|
7
|
+
#include "lzws_ext/io.h"
|
8
|
+
#include "lzws_ext/stream/compressor.h"
|
9
|
+
#include "lzws_ext/stream/decompressor.h"
|
10
|
+
#include "lzws_ext/string.h"
|
11
|
+
|
12
|
+
void Init_lzws_ext()
|
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);
|
34
|
+
|
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);
|
42
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
#include "lzws_ext/option.h"
|
7
|
+
|
8
|
+
VALUE lzws_ext_get_option(VALUE options, const char* name)
|
9
|
+
{
|
10
|
+
VALUE name_symbol = ID2SYM(rb_intern(name));
|
11
|
+
return rb_funcall(options, rb_intern("[]"), 1, name_symbol);
|
12
|
+
}
|
13
|
+
|
14
|
+
void lzws_ext_check_bool_type(VALUE option, const char* name)
|
15
|
+
{
|
16
|
+
int type = TYPE(option);
|
17
|
+
|
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));
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
// Ruby bindings for lzws library.
|
2
|
+
// Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
#if !defined(LZWS_EXT_OPTIONS_H)
|
5
|
+
#define LZWS_EXT_OPTIONS_H
|
6
|
+
|
7
|
+
#include "ruby.h"
|
8
|
+
|
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;
|
59
|
+
|
60
|
+
#endif // LZWS_EXT_OPTIONS_H
|