pr-zlib 1.0.5 → 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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/{CHANGES → CHANGES.md} +19 -6
  4. data/Gemfile +6 -0
  5. data/MANIFEST.md +20 -0
  6. data/{README → README.md} +29 -12
  7. data/Rakefile +11 -61
  8. data/bin/{minizip.rb → minirbgzip} +77 -65
  9. data/lib/pr/rbzlib/bytef.rb +16 -0
  10. data/lib/pr/rbzlib/bytef_arr.rb +29 -0
  11. data/lib/pr/rbzlib/bytef_str.rb +52 -0
  12. data/lib/pr/rbzlib/posf.rb +33 -0
  13. data/lib/pr/rbzlib.rb +1758 -1855
  14. data/lib/pr/zlib/deflate.rb +99 -0
  15. data/lib/pr/zlib/errors.rb +27 -0
  16. data/lib/pr/zlib/gzipfile.rb +315 -0
  17. data/lib/pr/zlib/gzipfile_errors.rb +19 -0
  18. data/lib/pr/zlib/gzipreader.rb +338 -0
  19. data/lib/pr/zlib/gzipwriter.rb +167 -0
  20. data/lib/pr/zlib/inflate.rb +114 -0
  21. data/lib/pr/zlib/zstream.rb +417 -0
  22. data/lib/pr/zlib.rb +25 -1466
  23. data/pr-zlib.gemspec +15 -15
  24. data/profile/bench_pr_zlib.rb +7 -5
  25. data/profile/bench_zlib.rb +7 -5
  26. data/profile/profile_pr_zlib_read.rb +3 -3
  27. data/profile/profile_pr_zlib_write.rb +3 -3
  28. data/spec/README.md +46 -0
  29. data/spec/rbzlib/bytef_arr_spec.rb +82 -0
  30. data/spec/rbzlib/bytef_spec.rb +72 -0
  31. data/spec/rbzlib/bytef_str_spec.rb +113 -0
  32. data/spec/rbzlib/posf_spec.rb +83 -0
  33. data/spec/rbzlib_spec.rb +170 -0
  34. data/spec/spec_helper.rb +27 -0
  35. data/spec/zlib/deflate_spec.rb +44 -0
  36. data/spec/zlib/gzip_file_spec.rb +86 -0
  37. data/spec/zlib/gzip_reader_spec.rb +276 -0
  38. data/spec/zlib/gzip_writer_spec.rb +275 -0
  39. data/spec/zlib/inflate_spec.rb +44 -0
  40. data/spec/zlib/zstream_spec.rb +156 -0
  41. data/spec/zlib_spec.rb +195 -0
  42. data.tar.gz.sig +0 -0
  43. metadata +68 -55
  44. metadata.gz.sig +0 -0
  45. data/MANIFEST +0 -20
  46. data/test/test_rbzlib.rb +0 -133
  47. data/test/test_rbzlib_bytef.rb +0 -76
  48. data/test/test_rbzlib_posf.rb +0 -56
  49. data/test/test_zlib.rb +0 -162
  50. data/test/test_zlib_deflate.rb +0 -55
  51. data/test/test_zlib_gzip_file.rb +0 -93
  52. data/test/test_zlib_gzip_reader.rb +0 -183
  53. data/test/test_zlib_gzip_writer.rb +0 -186
  54. data/test/test_zlib_inflate.rb +0 -55
  55. data/test/test_zlib_zstream.rb +0 -146
@@ -0,0 +1,338 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'gzipfile'
4
+
5
+ module Zlib
6
+ class GzipReader < GzipFile
7
+ include Enumerable
8
+
9
+ def lineno
10
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
11
+ @gz.lineno
12
+ end
13
+
14
+ def lineno=(lineno)
15
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
16
+ @gz.lineno = lineno
17
+ end
18
+
19
+ def eof
20
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
21
+ GZFILE_IS_FINISHED(@gz)
22
+ end
23
+ alias eof? :eof
24
+
25
+ def pos
26
+ if @gz.z.buf.nil?
27
+ @gz.z.stream.total_out
28
+ else
29
+ @gz.z.stream.total_out - @gz.z.buf.offset
30
+ end
31
+ end
32
+ alias tell :pos
33
+
34
+ def self.open(filename, level = Z_DEFAULT_COMPRESSION, strategy = Z_DEFAULT_STRATEGY, &blk)
35
+ GzipReader.gzfile_s_open(filename, 'rb', level, strategy, &blk)
36
+ end
37
+
38
+ def initialize(io, level = Z_DEFAULT_COMPRESSION, _strategy = Z_DEFAULT_STRATEGY)
39
+ gzfile_new(InflateFuncs, :gzfile_reader_end)
40
+ @gz.level = level
41
+ err = inflateInit2(@gz.z.stream, -MAX_WBITS)
42
+ if err != Z_OK
43
+ raise_zlib_error(err, @gz.stream.msg)
44
+ end
45
+ @gz.io = io
46
+ @gz.z.ZSTREAM_READY()
47
+ gzfile_read_header()
48
+ self
49
+ end
50
+
51
+ def rewind
52
+ gzfile_reader_rewind()
53
+ 0
54
+ end
55
+
56
+ def unused
57
+ gzfile_reader_get_unused()
58
+ end
59
+
60
+ def read(len = nil)
61
+ if len.nil?
62
+ return gzfile_read_all()
63
+ end
64
+
65
+ if len < 0
66
+ raise ArgumentError, "negative length #{len} given"
67
+ end
68
+
69
+ gzfile_read(len)
70
+ end
71
+
72
+ def getc
73
+ dst = gzfile_read(1)
74
+ dst ? dst[0] : dst
75
+ end
76
+
77
+ def readchar
78
+ dst = getc()
79
+ if dst.nil?
80
+ raise EOFError, 'end of file reached'
81
+ end
82
+ dst
83
+ end
84
+
85
+ def each_byte
86
+ while (c = getc)
87
+ yield(c)
88
+ end
89
+ nil
90
+ end
91
+
92
+ def ungetc(ch)
93
+ gzfile_ungetc(ch)
94
+ nil
95
+ end
96
+
97
+ def gets(rs = $/)
98
+ gzreader_gets(rs)
99
+ end
100
+
101
+ def readline(rs = $/)
102
+ gets(rs)
103
+ end
104
+
105
+ def each(rs = $/)
106
+ while (str = gzreader_gets(rs))
107
+ yield(str)
108
+ end
109
+ self
110
+ end
111
+ alias each_line :each
112
+
113
+ def readlines(rs = $/)
114
+ dst = []
115
+ while str = gzreader_gets(rs)
116
+ dst.push(str)
117
+ end
118
+ dst
119
+ end
120
+
121
+ private
122
+
123
+ def gzfile_reader_end_run
124
+ if GZFILE_IS_FINISHED(@gz) && (@gz.z.flags &
125
+ GZFILE_FLAG_FOOTER_FINISHED).zero?
126
+ gzfile_check_footer()
127
+ end
128
+ nil
129
+ end
130
+
131
+ def gzfile_reader_end
132
+ return if @gz.z.ZSTREAM_IS_CLOSING()
133
+ @gz.z.flags |= ZSTREAM_FLAG_CLOSING
134
+ begin
135
+ gzfile_reader_end_run()
136
+ ensure
137
+ @gz.z.zstream_end()
138
+ end
139
+ end
140
+
141
+ def gzfile_ungetc(c)
142
+ @gz.z.zstream_buffer_ungetc(c)
143
+ @gz.ungetc += 1
144
+ end
145
+
146
+ def gzfile_reader_rewind
147
+ n = @gz.z.stream.total_in
148
+ if @gz.z.input
149
+ n += @gz.z.input.length
150
+ end
151
+ @gz.io.seek(-n, 1)
152
+ gzfile_reset()
153
+ end
154
+
155
+ def gzfile_reader_get_unused
156
+ return nil if !@gz.z.ZSTREAM_IS_READY()
157
+ return nil if !GZFILE_IS_FINISHED(@gz)
158
+ if (@gz.z.flags & GZFILE_FLAG_FOOTER_FINISHED).zero?
159
+ gzfile_check_footer()
160
+ end
161
+ return nil if @gz.z.input.nil?
162
+ @gz.z.input.dup
163
+ end
164
+
165
+ def rscheck(rsptr, _rslen, rs)
166
+ raise RuntimeError, 'rs modified' if rs != rsptr
167
+ end
168
+
169
+ def gzreader_skip_linebreaks
170
+ # Skip consecutive newline characters for paragraph mode
171
+ while (c = getc)
172
+ case c
173
+ when "\n", "\r"
174
+ # Continue skipping
175
+ else
176
+ ungetc(c)
177
+ break
178
+ end
179
+ end
180
+ end
181
+
182
+ def gzreader_gets(rs = $/)
183
+ if rs && rs.class != String
184
+ raise TypeError, "wrong argument type #{rs.class} (expected String)"
185
+ end
186
+ if rs.nil?
187
+ dst = gzfile_read_all()
188
+ @gz.lineno += 1 if dst.length.nonzero?
189
+ return dst
190
+ end
191
+ if rs.length.zero?
192
+ rsptr = "\n\n"
193
+ rslen = 2
194
+ rspara = true
195
+ else
196
+ rsptr = rs
197
+ rslen = rs.length
198
+ rspara = false
199
+ end
200
+ if rspara
201
+ gzreader_skip_linebreaks
202
+ end
203
+ while @gz.z.buf.offset < rslen
204
+ if @gz.z.ZSTREAM_IS_FINISHED()
205
+ @gz.lineno += 1 if @gz.z.buf.offset > 0
206
+ return gzfile_read(rslen)
207
+ end
208
+ gzfile_read_more()
209
+ end
210
+
211
+ ap = 0
212
+ n = rslen
213
+ loop do
214
+ if n > @gz.z.buf.offset
215
+ break if @gz.z.ZSTREAM_IS_FINISHED()
216
+ gzfile_read_more()
217
+ ap = n - rslen
218
+ end
219
+
220
+ rscheck(rsptr, rslen, rs) if !rspara
221
+ res = @gz.z.buf.buffer[ap, @gz.z.buf.offset - n + 1].index(rsptr[0])
222
+
223
+ if res.nil?
224
+ n = @gz.z.buf.offset + 1
225
+ else
226
+ n += (res - ap)
227
+ ap = res
228
+ break if rslen == 1 || @gz.z.buf.buffer[ap, rslen] == rsptr
229
+ ap += 1
230
+ n += 1
231
+ end
232
+ end
233
+
234
+ @gz.lineno += 1
235
+ dst = gzfile_read(n)
236
+ if rspara
237
+ gzreader_skip_linebreaks()
238
+ end
239
+ dst
240
+ end
241
+
242
+ def gzfile_read(len)
243
+ if len < 0
244
+ raise ArgumentError, "negative length #{len} given"
245
+ end
246
+
247
+ if len.zero?
248
+ return ''
249
+ end
250
+
251
+ if @gz.z.buf.nil?
252
+ @gz.z.buf = Bytef.new(0.chr * len)
253
+ end
254
+
255
+ while !@gz.z.ZSTREAM_IS_FINISHED() && @gz.z.buf.offset < len
256
+ gzfile_read_more()
257
+ end
258
+
259
+ if GZFILE_IS_FINISHED(@gz)
260
+ if (@gz.z.flags & GZFILE_FLAG_FOOTER_FINISHED).zero?
261
+ gzfile_check_footer()
262
+ end
263
+ return nil
264
+ end
265
+
266
+ dst = @gz.z.zstream_shift_buffer(len)
267
+ gzfile_calc_crc(dst)
268
+ dst
269
+ end
270
+
271
+ def gzfile_read_all
272
+ while !@gz.z.ZSTREAM_IS_FINISHED()
273
+ gzfile_read_more()
274
+ end
275
+ if GZFILE_IS_FINISHED(@gz)
276
+ if (@gz.z.flags & GZFILE_FLAG_FOOTER_FINISHED).zero?
277
+ gzfile_check_footer()
278
+ end
279
+ return ''
280
+ end
281
+
282
+ dst = @gz.z.zstream_detach_buffer()
283
+ gzfile_calc_crc(dst)
284
+ dst
285
+ end
286
+
287
+ def gzfile_read_raw
288
+ str = @gz.io.read(GZFILE_READ_SIZE)
289
+ if str && str.class != String
290
+ raise TypeError, "wrong argument type #{rs.class} (expected String)"
291
+ end
292
+ str
293
+ end
294
+
295
+ def gzfile_read_raw_ensure(size)
296
+ while @gz.z.input.nil? || @gz.z.input.length < size
297
+ str = gzfile_read_raw()
298
+ return false if str.nil?
299
+ @gz.z.zstream_append_input(str, str.length)
300
+ end
301
+ true
302
+ end
303
+
304
+ def gzfile_read_raw_until_zero(offset)
305
+ ap = nil
306
+
307
+ loop do
308
+ ap = @gz.z.input[offset, @gz.z.input.length - offset].index(0.chr)
309
+ break if ap
310
+ str = gzfile_read_raw()
311
+
312
+ raise Error, 'unexpected end of file' if str.nil?
313
+
314
+ offset = @gz.z.input.length
315
+ @gz.z.zstream_append_input(str, str.length)
316
+ end
317
+
318
+ ap
319
+ end
320
+
321
+ def gzfile_read_more
322
+ while !@gz.z.ZSTREAM_IS_FINISHED()
323
+ str = gzfile_read_raw()
324
+ if str.nil?
325
+ if !@gz.z.ZSTREAM_IS_FINISHED()
326
+ raise Error, 'unexpected end of file'
327
+ end
328
+ break
329
+ end
330
+ if str.length > 0
331
+ @gz.z.zstream_run(str, str.length, Z_SYNC_FLUSH)
332
+ end
333
+ break if @gz.z.buf.offset > 0
334
+ end
335
+ @gz.z.buf.offset
336
+ end
337
+ end
338
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'gzipfile'
4
+
5
+ module Zlib
6
+ class GzipWriter < GzipFile
7
+
8
+ def mtime=(mtime)
9
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
10
+
11
+ if (@gz.z.flags & GZFILE_FLAG_HEADER_FINISHED).nonzero?
12
+ raise GzipFile::Error, 'header is already written'
13
+ end
14
+
15
+ @gz.mtime = mtime.to_i
16
+ end
17
+
18
+ def orig_name=(str)
19
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
20
+
21
+ if (@gz.z.flags & GZFILE_FLAG_HEADER_FINISHED).nonzero?
22
+ raise GzipFile::Error, 'header is already written'
23
+ end
24
+
25
+ ap = str[0.chr]
26
+ @gz.orig_name = ap ? str[0, ap] : str.dup
27
+ end
28
+
29
+ def comment=(str)
30
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
31
+
32
+ if (@gz.z.flags & GZFILE_FLAG_HEADER_FINISHED).nonzero?
33
+ raise GzipFile::Error, 'header is already written'
34
+ end
35
+
36
+ @gz.comment = str.dup
37
+ end
38
+
39
+ def pos
40
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
41
+ @gz.z.stream.total_in
42
+ end
43
+
44
+ alias tell :pos
45
+
46
+ def self.open(filename, level = Z_DEFAULT_COMPRESSION, strategy = Z_DEFAULT_STRATEGY, &blk)
47
+ GzipWriter.gzfile_s_open(filename, 'wb', level, strategy, &blk)
48
+ end
49
+
50
+ def initialize(io, level = nil, strategy = nil)
51
+ level = Z_DEFAULT_COMPRESSION if level.nil?
52
+ strategy = Z_DEFAULT_STRATEGY if strategy.nil?
53
+
54
+ gzfile_new(DeflateFuncs, :gzfile_writer_end)
55
+ @gz.level = level
56
+
57
+ err = deflateInit2(
58
+ @gz.z.stream,
59
+ @gz.level,
60
+ Z_DEFLATED,
61
+ -MAX_WBITS,
62
+ DEF_MEM_LEVEL,
63
+ strategy
64
+ )
65
+
66
+ if err != Z_OK
67
+ raise_zlib_error(err, @gz.stream.msg)
68
+ end
69
+
70
+ @gz.io = io
71
+ @gz.z.ZSTREAM_READY()
72
+ end
73
+
74
+ def flush(v_flush = Z_SYNC_FLUSH)
75
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
76
+
77
+ if v_flush != Z_NO_FLUSH
78
+ @gz.z.zstream_run('', 0, v_flush)
79
+ end
80
+
81
+ gzfile_write_raw()
82
+
83
+ if defined?(@gz.io.flush)
84
+ @gz.io.flush()
85
+ end
86
+
87
+ self
88
+ end
89
+
90
+ def write(str)
91
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
92
+ str = str.to_s
93
+ gzfile_write(str, str.length)
94
+ str.length
95
+ end
96
+
97
+ def putc(ch)
98
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
99
+ gzfile_write(ch.chr, 1)
100
+ ch
101
+ end
102
+
103
+ def <<(str)
104
+ @gz.io << str
105
+ end
106
+
107
+ def printf(*arg)
108
+ @gz.io.printf(*arg)
109
+ end
110
+
111
+ def print(*arg)
112
+ @gz.io.print(*arg)
113
+ end
114
+
115
+ def puts(str)
116
+ @gz.io.puts(str)
117
+ end
118
+
119
+ def gzfile_write_raw
120
+ if @gz.z.buf.offset > 0
121
+ str = @gz.z.zstream_detach_buffer()
122
+ @gz.io.write(str)
123
+ if (@gz.z.flags & GZFILE_FLAG_SYNC).nonzero? && defined?(@gz.io.flush)
124
+ @gz.io.flush()
125
+ end
126
+ end
127
+ end
128
+
129
+ private :gzfile_write_raw
130
+
131
+ def gzfile_write(str, len)
132
+ if (@gz.z.flags & GZFILE_FLAG_HEADER_FINISHED).zero?
133
+ gzfile_make_header()
134
+ end
135
+
136
+ if len > 0 || (@gz.z.flags & GZFILE_FLAG_SYNC)
137
+ @gz.crc = crc32(@gz.crc, str, len)
138
+ @gz.z.zstream_run(str, len, (@gz.z.flags & GZFILE_FLAG_SYNC).nonzero? ?
139
+ Z_SYNC_FLUSH : Z_NO_FLUSH)
140
+ end
141
+ gzfile_write_raw()
142
+ end
143
+
144
+ private :gzfile_write
145
+
146
+ def gzfile_writer_end_run
147
+ if (@gz.z.flags & GZFILE_FLAG_HEADER_FINISHED).zero?
148
+ gzfile_make_header()
149
+ end
150
+ @gz.z.zstream_run('', 0, Z_FINISH)
151
+ gzfile_make_footer()
152
+ gzfile_write_raw()
153
+
154
+ nil
155
+ end
156
+
157
+ def gzfile_writer_end
158
+ return if @gz.z.ZSTREAM_IS_CLOSING()
159
+ @gz.z.flags |= ZSTREAM_FLAG_CLOSING
160
+ begin
161
+ gzfile_writer_end_run()
162
+ ensure
163
+ @gz.z.zstream_end()
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'zstream'
4
+
5
+ module Zlib
6
+ class Inflate < ZStream
7
+
8
+ def self.inflate_run(src)
9
+ @z.zstream_run(src, src.length, Z_SYNC_FLUSH)
10
+ @z.zstream_run('', 0, Z_FINISH)
11
+ @z.zstream_detach_buffer()
12
+ end
13
+
14
+ def self.inflate(src)
15
+ @z = ZStream.new
16
+ @z.zstream_init(InflateFuncs)
17
+ err = inflateInit(@z.stream)
18
+ if err != Z_OK
19
+ raise_zlib_error(err, @z.stream.msg)
20
+ end
21
+ @z.ZSTREAM_READY()
22
+ begin
23
+ dst = inflate_run(src)
24
+ ensure
25
+ @z.zstream_end
26
+ end
27
+ dst
28
+ end
29
+
30
+ def do_inflate(src)
31
+ if src.nil?
32
+ @z.zstream_run('', 0, Z_FINISH)
33
+ return
34
+ end
35
+ if src.length > 0
36
+ @z.zstream_run(src, src.length, Z_SYNC_FLUSH)
37
+ end
38
+ end
39
+ private :do_inflate
40
+
41
+ def initialize(wbits = MAX_WBITS)
42
+ @z = ZStream.new
43
+ @z.zstream_init(InflateFuncs)
44
+ err = inflateInit2(@z.stream, wbits)
45
+ if err != Z_OK
46
+ raise_zlib_error(err, @z.stream.msg)
47
+ end
48
+ @z.ZSTREAM_READY()
49
+ end
50
+
51
+ def inflate(src)
52
+ if @z.ZSTREAM_IS_FINISHED()
53
+ if src.nil?
54
+ dst = @z.zstream_detach_buffer()
55
+ else
56
+ @z.zstream_append_buffer(src, src.lenth)
57
+ dst = ''
58
+ end
59
+ else
60
+ do_inflate(src)
61
+ dst = @z.zstream_detach_buffer()
62
+ if @z.ZSTREAM_IS_FINISHED()
63
+ @z.zstream_passthrough_input()
64
+ end
65
+ end
66
+ if block_given?
67
+ yield dst
68
+ else
69
+ dst
70
+ end
71
+ end
72
+
73
+ def <<(src)
74
+ if @z.ZSTREAM_IS_FINISHED()
75
+ if src
76
+ @z.zstream_append_buffer(src, src.length)
77
+ end
78
+ else
79
+ do_inflate(src)
80
+ if @z.ZSTREAM_IS_FINISHED()
81
+ @z.zstream_passthrough_input()
82
+ end
83
+ end
84
+ self
85
+ end
86
+
87
+ def sync
88
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
89
+ @z.zstream_sync(src, src.length)
90
+ end
91
+
92
+ def sync_point?
93
+ err = inflateSyncPoint(@z.stream)
94
+ return true if err == 1
95
+
96
+ if err != Z_OK
97
+ raise_zlib_error(err, @z.stream.msg)
98
+ end
99
+
100
+ false
101
+ end
102
+
103
+ def set_dictionary(dic)
104
+ src = dic
105
+ err = inflateSetDictionary(@z.stream, src, src.length)
106
+
107
+ if err != Z_OK
108
+ raise_zlib_error(err, @z.stream.msg)
109
+ end
110
+
111
+ dic
112
+ end
113
+ end
114
+ end