ruby-lzws 1.1.3 → 1.2.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 +55 -65
- data/ext/extconf.rb +9 -2
- data/ext/lzws_ext/buffer.c +18 -4
- data/ext/lzws_ext/common.h +3 -0
- data/ext/lzws_ext/error.c +0 -1
- data/ext/lzws_ext/error.h +2 -1
- data/ext/lzws_ext/io.c +4 -10
- data/ext/lzws_ext/main.c +2 -1
- data/ext/lzws_ext/option.c +22 -7
- data/ext/lzws_ext/option.h +28 -23
- data/ext/lzws_ext/stream/compressor.c +29 -39
- data/ext/lzws_ext/stream/compressor.h +5 -4
- data/ext/lzws_ext/stream/decompressor.c +24 -31
- data/ext/lzws_ext/stream/decompressor.h +5 -4
- data/ext/lzws_ext/string.c +60 -75
- data/lib/lzws/file.rb +4 -0
- data/lib/lzws/option.rb +32 -33
- data/lib/lzws/stream/abstract.rb +9 -12
- 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 +71 -52
- data/lib/lzws/stream/writer.rb +10 -5
- data/lib/lzws/stream/writer_helpers.rb +6 -5
- data/lib/lzws/validation.rb +15 -2
- data/lib/lzws/version.rb +1 -1
- metadata +10 -24
data/lib/lzws/file.rb
CHANGED
@@ -20,6 +20,8 @@ module LZWS
|
|
20
20
|
open_files(source, destination) do |source_io, destination_io|
|
21
21
|
LZWS._native_compress_io source_io, destination_io, options
|
22
22
|
end
|
23
|
+
|
24
|
+
nil
|
23
25
|
end
|
24
26
|
|
25
27
|
def self.decompress(source, destination, options = {})
|
@@ -31,6 +33,8 @@ module LZWS
|
|
31
33
|
open_files(source, destination) do |source_io, destination_io|
|
32
34
|
LZWS._native_decompress_io source_io, destination_io, options
|
33
35
|
end
|
36
|
+
|
37
|
+
nil
|
34
38
|
end
|
35
39
|
|
36
40
|
private_class_method def self.open_files(source, destination, &_block)
|
data/lib/lzws/option.rb
CHANGED
@@ -8,45 +8,37 @@ require_relative "validation"
|
|
8
8
|
|
9
9
|
module LZWS
|
10
10
|
module Option
|
11
|
-
|
12
|
-
|
13
|
-
DEFAULT_BUFFER_LENGTH = 0
|
14
|
-
LOWEST_MAX_CODE_BIT_LENGTH = 9
|
15
|
-
BIGGEST_MAX_CODE_BIT_LENGTH = 16
|
16
|
-
|
17
|
-
DECOMPRESSOR_DEFAULTS = {
|
18
|
-
:without_magic_header => false,
|
19
|
-
:msb => false,
|
20
|
-
:unaligned_bit_groups => false,
|
21
|
-
:quiet => false
|
22
|
-
}
|
23
|
-
.freeze
|
24
|
-
|
25
|
-
COMPRESSOR_DEFAULTS = DECOMPRESSOR_DEFAULTS.merge(
|
26
|
-
:max_code_bit_length => BIGGEST_MAX_CODE_BIT_LENGTH,
|
27
|
-
:block_mode => true
|
28
|
-
)
|
29
|
-
.freeze
|
11
|
+
DEFAULT_BUFFER_LENGTH = 0
|
30
12
|
|
31
13
|
def self.get_compressor_options(options, buffer_length_names)
|
32
14
|
Validation.validate_hash options
|
33
15
|
|
34
16
|
buffer_length_defaults = buffer_length_names.each_with_object({}) { |name, defaults| defaults[name] = DEFAULT_BUFFER_LENGTH }
|
35
|
-
options =
|
17
|
+
options = buffer_length_defaults.merge options
|
36
18
|
|
37
19
|
buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
|
38
20
|
|
39
21
|
max_code_bit_length = options[:max_code_bit_length]
|
40
|
-
|
22
|
+
unless max_code_bit_length.nil?
|
23
|
+
Validation.validate_positive_integer max_code_bit_length
|
24
|
+
raise ValidateError, "invalid max code bit length" if
|
25
|
+
max_code_bit_length < LOWEST_MAX_CODE_BIT_LENGTH || max_code_bit_length > BIGGEST_MAX_CODE_BIT_LENGTH
|
26
|
+
end
|
41
27
|
|
42
|
-
|
43
|
-
|
28
|
+
without_magic_header = options[:without_magic_header]
|
29
|
+
Validation.validate_bool without_magic_header unless without_magic_header.nil?
|
44
30
|
|
45
|
-
|
46
|
-
Validation.validate_bool
|
47
|
-
|
48
|
-
|
49
|
-
Validation.validate_bool
|
31
|
+
block_mode = options[:block_mode]
|
32
|
+
Validation.validate_bool block_mode unless block_mode.nil?
|
33
|
+
|
34
|
+
msb = options[:msb]
|
35
|
+
Validation.validate_bool msb unless msb.nil?
|
36
|
+
|
37
|
+
unaligned_bit_groups = options[:unaligned_bit_groups]
|
38
|
+
Validation.validate_bool unaligned_bit_groups unless unaligned_bit_groups.nil?
|
39
|
+
|
40
|
+
quiet = options[:quiet]
|
41
|
+
Validation.validate_bool quiet unless quiet.nil?
|
50
42
|
|
51
43
|
options
|
52
44
|
end
|
@@ -55,14 +47,21 @@ module LZWS
|
|
55
47
|
Validation.validate_hash options
|
56
48
|
|
57
49
|
buffer_length_defaults = buffer_length_names.each_with_object({}) { |name, defaults| defaults[name] = DEFAULT_BUFFER_LENGTH }
|
58
|
-
options =
|
50
|
+
options = buffer_length_defaults.merge options
|
59
51
|
|
60
52
|
buffer_length_names.each { |name| Validation.validate_not_negative_integer options[name] }
|
61
53
|
|
62
|
-
|
63
|
-
Validation.validate_bool
|
64
|
-
|
65
|
-
|
54
|
+
without_magic_header = options[:without_magic_header]
|
55
|
+
Validation.validate_bool without_magic_header unless without_magic_header.nil?
|
56
|
+
|
57
|
+
msb = options[:msb]
|
58
|
+
Validation.validate_bool msb unless msb.nil?
|
59
|
+
|
60
|
+
unaligned_bit_groups = options[:unaligned_bit_groups]
|
61
|
+
Validation.validate_bool unaligned_bit_groups unless unaligned_bit_groups.nil?
|
62
|
+
|
63
|
+
quiet = options[:quiet]
|
64
|
+
Validation.validate_bool quiet unless quiet.nil?
|
66
65
|
|
67
66
|
options
|
68
67
|
end
|
data/lib/lzws/stream/abstract.rb
CHANGED
@@ -17,23 +17,19 @@ module LZWS
|
|
17
17
|
|
18
18
|
include Delegates
|
19
19
|
|
20
|
-
attr_reader :io
|
21
|
-
|
22
|
-
attr_reader :external_encoding
|
23
|
-
attr_reader :internal_encoding
|
24
|
-
attr_reader :transcode_options
|
25
|
-
attr_reader :pos
|
20
|
+
attr_reader :io, :stat, :external_encoding, :internal_encoding, :transcode_options, :pos
|
21
|
+
|
26
22
|
alias tell pos
|
27
23
|
|
28
|
-
def initialize(io,
|
24
|
+
def initialize(io, options = {})
|
29
25
|
@raw_stream = create_raw_stream
|
30
26
|
|
31
27
|
Validation.validate_io io
|
32
28
|
@io = io
|
33
29
|
|
34
|
-
@stat = Stat.new @io.stat
|
30
|
+
@stat = Stat.new @io.stat if @io.respond_to? :stat
|
35
31
|
|
36
|
-
set_encoding external_encoding, internal_encoding, transcode_options
|
32
|
+
set_encoding options[:external_encoding], options[:internal_encoding], options[:transcode_options]
|
37
33
|
reset_buffer
|
38
34
|
reset_io_advise
|
39
35
|
|
@@ -50,8 +46,8 @@ module LZWS
|
|
50
46
|
|
51
47
|
protected def reset_io_advise
|
52
48
|
# Both compressor and decompressor need sequential io access.
|
53
|
-
@io.advise :sequential
|
54
|
-
rescue ::Errno::ESPIPE
|
49
|
+
@io.advise :sequential if @io.respond_to? :advise
|
50
|
+
rescue ::Errno::ESPIPE
|
55
51
|
# ok
|
56
52
|
end
|
57
53
|
|
@@ -126,7 +122,8 @@ module LZWS
|
|
126
122
|
def rewind
|
127
123
|
@raw_stream = create_raw_stream
|
128
124
|
|
129
|
-
@io.rewind
|
125
|
+
@io.rewind if @io.respond_to? :rewind
|
126
|
+
|
130
127
|
reset_buffer
|
131
128
|
reset_io_advise
|
132
129
|
|
@@ -27,9 +27,9 @@ module LZWS
|
|
27
27
|
nil
|
28
28
|
end
|
29
29
|
|
30
|
-
protected def
|
30
|
+
protected def more_destination(&writer)
|
31
31
|
result_bytesize = write_result(&writer)
|
32
|
-
raise NotEnoughDestinationError, "not enough destination" if result_bytesize
|
32
|
+
raise NotEnoughDestinationError, "not enough destination" if result_bytesize.zero?
|
33
33
|
end
|
34
34
|
|
35
35
|
protected def write_result(&_writer)
|
@@ -50,6 +50,8 @@ module LZWS
|
|
50
50
|
|
51
51
|
@native_stream.close
|
52
52
|
@is_closed = true
|
53
|
+
|
54
|
+
nil
|
53
55
|
end
|
54
56
|
|
55
57
|
def closed?
|
@@ -35,7 +35,7 @@ module LZWS
|
|
35
35
|
|
36
36
|
if need_more_destination
|
37
37
|
source = source.byteslice bytes_written, source.bytesize - bytes_written
|
38
|
-
|
38
|
+
more_destination(&writer)
|
39
39
|
next
|
40
40
|
end
|
41
41
|
|
@@ -61,7 +61,7 @@ module LZWS
|
|
61
61
|
need_more_destination = @native_stream.finish
|
62
62
|
|
63
63
|
if need_more_destination
|
64
|
-
|
64
|
+
more_destination(&writer)
|
65
65
|
next
|
66
66
|
end
|
67
67
|
|
@@ -69,8 +69,6 @@ module LZWS
|
|
69
69
|
end
|
70
70
|
|
71
71
|
super
|
72
|
-
|
73
|
-
nil
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|
@@ -34,7 +34,7 @@ module LZWS
|
|
34
34
|
|
35
35
|
if need_more_destination
|
36
36
|
source = source.byteslice bytes_read, source.bytesize - bytes_read
|
37
|
-
|
37
|
+
more_destination(&writer)
|
38
38
|
next
|
39
39
|
end
|
40
40
|
|
@@ -51,8 +51,6 @@ module LZWS
|
|
51
51
|
Validation.validate_proc writer
|
52
52
|
|
53
53
|
super
|
54
|
-
|
55
|
-
nil
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
data/lib/lzws/stream/reader.rb
CHANGED
@@ -20,79 +20,60 @@ module LZWS
|
|
20
20
|
|
21
21
|
initialize_source_buffer_length
|
22
22
|
reset_io_remainder
|
23
|
+
reset_need_to_flush
|
23
24
|
|
24
25
|
@lineno = 0
|
25
26
|
end
|
26
27
|
|
28
|
+
protected def create_raw_stream
|
29
|
+
Raw::Decompressor.new @options
|
30
|
+
end
|
31
|
+
|
27
32
|
protected def initialize_source_buffer_length
|
28
33
|
source_buffer_length = @options[:source_buffer_length]
|
29
34
|
Validation.validate_not_negative_integer source_buffer_length unless source_buffer_length.nil?
|
30
35
|
|
31
36
|
source_buffer_length = Buffer::DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR \
|
32
|
-
if source_buffer_length
|
37
|
+
if source_buffer_length.nil? || source_buffer_length.zero?
|
33
38
|
|
34
39
|
@source_buffer_length = source_buffer_length
|
35
40
|
end
|
36
41
|
|
37
|
-
protected def create_raw_stream
|
38
|
-
Raw::Decompressor.new @options
|
39
|
-
end
|
40
|
-
|
41
42
|
protected def reset_io_remainder
|
42
43
|
@io_remainder = ::String.new :encoding => ::Encoding::BINARY
|
43
44
|
end
|
44
45
|
|
46
|
+
protected def reset_need_to_flush
|
47
|
+
@need_to_flush = false
|
48
|
+
end
|
49
|
+
|
45
50
|
# -- synchronous --
|
46
51
|
|
47
52
|
def read(bytes_to_read = nil, out_buffer = nil)
|
48
53
|
Validation.validate_not_negative_integer bytes_to_read unless bytes_to_read.nil?
|
49
54
|
Validation.validate_string out_buffer unless out_buffer.nil?
|
50
55
|
|
51
|
-
return ::String.new :encoding => ::Encoding::BINARY if bytes_to_read == 0
|
52
|
-
|
53
56
|
unless bytes_to_read.nil?
|
57
|
+
return ::String.new :encoding => ::Encoding::BINARY if bytes_to_read.zero?
|
54
58
|
return nil if eof?
|
55
59
|
|
56
|
-
|
60
|
+
append_io_data @io.read(@source_buffer_length) while @buffer.bytesize < bytes_to_read && !@io.eof?
|
61
|
+
flush_io_data if @buffer.bytesize < bytes_to_read
|
57
62
|
|
58
63
|
return read_bytes_from_buffer bytes_to_read, out_buffer
|
59
64
|
end
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
result = @buffer
|
64
|
-
reset_buffer
|
65
|
-
@pos += result.bytesize
|
66
|
+
append_io_data @io.read(@source_buffer_length) until @io.eof?
|
67
|
+
flush_io_data
|
66
68
|
|
67
|
-
|
68
|
-
result = transcode_to_internal result
|
69
|
-
result = out_buffer.replace result unless out_buffer.nil?
|
70
|
-
|
71
|
-
result
|
72
|
-
end
|
73
|
-
|
74
|
-
protected def read_more_to_buffer
|
75
|
-
io_data = @io.read @source_buffer_length
|
76
|
-
append_io_data_to_buffer io_data
|
77
|
-
end
|
78
|
-
|
79
|
-
def readpartial(bytes_to_read = nil, out_buffer = nil)
|
80
|
-
raise ::EOFError if eof?
|
81
|
-
|
82
|
-
readpartial_to_buffer until @buffer.bytesize >= bytes_to_read || @io.eof?
|
83
|
-
|
84
|
-
read_bytes_from_buffer bytes_to_read, out_buffer
|
85
|
-
end
|
86
|
-
|
87
|
-
protected def readpartial_to_buffer
|
88
|
-
io_data = @io.readpartial @source_buffer_length
|
89
|
-
append_io_data_to_buffer io_data
|
69
|
+
read_buffer out_buffer
|
90
70
|
end
|
91
71
|
|
92
72
|
def rewind
|
93
73
|
raw_wrapper :close
|
94
74
|
|
95
75
|
reset_io_remainder
|
76
|
+
reset_need_to_flush
|
96
77
|
|
97
78
|
super
|
98
79
|
end
|
@@ -103,25 +84,61 @@ module LZWS
|
|
103
84
|
super
|
104
85
|
end
|
105
86
|
|
87
|
+
def eof?
|
88
|
+
empty? && @io.eof?
|
89
|
+
end
|
90
|
+
|
106
91
|
# -- asynchronous --
|
107
92
|
|
93
|
+
def readpartial(bytes_to_read, out_buffer = nil)
|
94
|
+
read_more_nonblock(bytes_to_read, out_buffer) { @io.readpartial @source_buffer_length }
|
95
|
+
end
|
96
|
+
|
108
97
|
def read_nonblock(bytes_to_read, out_buffer = nil, *options)
|
109
|
-
|
98
|
+
read_more_nonblock(bytes_to_read, out_buffer) { @io.read_nonblock(@source_buffer_length, *options) }
|
99
|
+
end
|
100
|
+
|
101
|
+
protected def read_more_nonblock(bytes_to_read, out_buffer, &_block)
|
102
|
+
Validation.validate_not_negative_integer bytes_to_read
|
103
|
+
Validation.validate_string out_buffer unless out_buffer.nil?
|
104
|
+
|
105
|
+
return ::String.new :encoding => ::Encoding::BINARY if bytes_to_read.zero?
|
106
|
+
|
107
|
+
io_provided_eof_error = false
|
110
108
|
|
111
|
-
|
109
|
+
if @buffer.bytesize < bytes_to_read
|
110
|
+
begin
|
111
|
+
append_io_data yield
|
112
|
+
rescue ::EOFError
|
113
|
+
io_provided_eof_error = true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
flush_io_data if @buffer.bytesize < bytes_to_read
|
118
|
+
raise ::EOFError if empty? && io_provided_eof_error
|
112
119
|
|
113
120
|
read_bytes_from_buffer bytes_to_read, out_buffer
|
114
121
|
end
|
115
122
|
|
116
|
-
|
117
|
-
|
118
|
-
|
123
|
+
# -- common --
|
124
|
+
|
125
|
+
protected def append_io_data(io_data)
|
126
|
+
io_portion = @io_remainder + io_data
|
127
|
+
bytes_read = raw_wrapper :read, io_portion
|
128
|
+
@io_remainder = io_portion.byteslice bytes_read, io_portion.bytesize - bytes_read
|
129
|
+
|
130
|
+
# Even empty io data may require flush.
|
131
|
+
@need_to_flush = true
|
119
132
|
end
|
120
133
|
|
121
|
-
|
134
|
+
protected def flush_io_data
|
135
|
+
raw_wrapper :flush
|
122
136
|
|
123
|
-
|
124
|
-
|
137
|
+
@need_to_flush = false
|
138
|
+
end
|
139
|
+
|
140
|
+
protected def empty?
|
141
|
+
!@need_to_flush && @buffer.bytesize.zero?
|
125
142
|
end
|
126
143
|
|
127
144
|
protected def read_bytes_from_buffer(bytes_to_read, out_buffer)
|
@@ -136,18 +153,20 @@ module LZWS
|
|
136
153
|
result
|
137
154
|
end
|
138
155
|
|
139
|
-
protected def
|
140
|
-
|
141
|
-
|
142
|
-
@
|
156
|
+
protected def read_buffer(out_buffer)
|
157
|
+
result = @buffer
|
158
|
+
reset_buffer
|
159
|
+
@pos += result.bytesize
|
143
160
|
|
144
|
-
|
145
|
-
|
146
|
-
|
161
|
+
result.force_encoding @external_encoding unless @external_encoding.nil?
|
162
|
+
result = transcode_to_internal result
|
163
|
+
|
164
|
+
result = out_buffer.replace result unless out_buffer.nil?
|
165
|
+
result
|
147
166
|
end
|
148
167
|
|
149
168
|
protected def transcode_to_internal(data)
|
150
|
-
data = data.encode @internal_encoding,
|
169
|
+
data = data.encode @internal_encoding, **@transcode_options unless @internal_encoding.nil?
|
151
170
|
data
|
152
171
|
end
|
153
172
|
|
data/lib/lzws/stream/writer.rb
CHANGED
@@ -64,7 +64,7 @@ module LZWS
|
|
64
64
|
end
|
65
65
|
|
66
66
|
protected def write_remaining_buffer
|
67
|
-
return nil if @buffer.bytesize
|
67
|
+
return nil if @buffer.bytesize.zero?
|
68
68
|
|
69
69
|
@io.write @buffer
|
70
70
|
|
@@ -77,6 +77,11 @@ module LZWS
|
|
77
77
|
|
78
78
|
# -- asynchronous --
|
79
79
|
|
80
|
+
# IO write nonblock can raise wait writable error.
|
81
|
+
# After resolving this error user may provide same content again.
|
82
|
+
# It is not possible to revert accepted content after error.
|
83
|
+
# So we have to accept content after processing IO write nonblock.
|
84
|
+
# It means that first write nonblock won't call IO write nonblock.
|
80
85
|
def write_nonblock(object, *options)
|
81
86
|
return 0 unless write_remaining_buffer_nonblock(*options)
|
82
87
|
|
@@ -120,14 +125,14 @@ module LZWS
|
|
120
125
|
end
|
121
126
|
|
122
127
|
protected def write_remaining_buffer_nonblock(*options)
|
123
|
-
return true if @buffer.bytesize
|
128
|
+
return true if @buffer.bytesize.zero?
|
124
129
|
|
125
130
|
bytes_written = @io.write_nonblock @buffer, *options
|
126
|
-
return false if bytes_written
|
131
|
+
return false if bytes_written.zero?
|
127
132
|
|
128
133
|
@buffer = @buffer.byteslice bytes_written, @buffer.bytesize - bytes_written
|
129
134
|
|
130
|
-
@buffer.bytesize
|
135
|
+
@buffer.bytesize.zero?
|
131
136
|
end
|
132
137
|
|
133
138
|
protected def raw_nonblock_wrapper(method_name, *args)
|
@@ -137,7 +142,7 @@ module LZWS
|
|
137
142
|
# -- common --
|
138
143
|
|
139
144
|
protected def transcode(data)
|
140
|
-
data = data.encode @external_encoding,
|
145
|
+
data = data.encode @external_encoding, **@transcode_options unless @external_encoding.nil?
|
141
146
|
data
|
142
147
|
end
|
143
148
|
end
|