pr-zlib 1.0.6 → 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} +13 -7
  4. data/Gemfile +6 -0
  5. data/MANIFEST.md +20 -0
  6. data/{README → README.md} +29 -12
  7. data/Rakefile +10 -60
  8. data/bin/minirbgzip +4 -2
  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 +14 -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 +65 -53
  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,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'zstream'
4
+
5
+ module Zlib
6
+ class Deflate < ZStream
7
+
8
+ def self.deflate_run(src)
9
+ @z.zstream_run(src, src.length, Z_FINISH)
10
+ @z.zstream_detach_buffer()
11
+ end
12
+
13
+ def self.deflate(src, level = Z_DEFAULT_COMPRESSION)
14
+ @z = ZStream.new
15
+ @z.zstream_init(DeflateFuncs)
16
+ err = deflateInit(@z.stream, level)
17
+ if err != Z_OK
18
+ raise_zlib_error(err, @z.stream.msg)
19
+ end
20
+ @z.ZSTREAM_READY()
21
+
22
+ begin
23
+ dst = deflate_run(src)
24
+ ensure
25
+ @z.zstream_end()
26
+ end
27
+ dst
28
+ end
29
+
30
+ def initialize(level = Z_DEFAULT_COMPRESSION, wbits = MAX_WBITS, memlevel = DEF_MEM_LEVEL, strategy = Z_DEFAULT_STRATEGY)
31
+ @z = ZStream.new
32
+ @z.zstream_init(DeflateFuncs)
33
+ err = deflateInit2(@z.stream, level, Z_DEFLATED, wbits, memlevel, strategy)
34
+ if err != Z_OK
35
+ raise_zlib_error(err, @z.stream.msg)
36
+ end
37
+ @z.ZSTREAM_READY()
38
+ end
39
+
40
+ def initialize_copy(orig)
41
+ z1 = @z
42
+ z2 = orig.z
43
+ err = deflateCopy(z1.stream, z2.stream)
44
+ if err != Z_OK
45
+ raise_zlib_error(err, 0)
46
+ end
47
+ z1.flags = z2.flags
48
+ end
49
+
50
+ def do_deflate(src, flush)
51
+ if src.nil?
52
+ @z.zstream_run('', 0, Z_FINISH)
53
+ return
54
+ end
55
+ if flush != Z_NO_FLUSH || (src && src.length > 0)
56
+ @z.zstream_run(src, src.length, flush)
57
+ end
58
+ end
59
+ private :do_deflate
60
+
61
+ def deflate(src, flush = Z_NO_FLUSH)
62
+ do_deflate(src, flush)
63
+ @z.zstream_detach_buffer
64
+ end
65
+
66
+ def <<(src)
67
+ do_deflate(src, Z_NO_FLUSH)
68
+ self
69
+ end
70
+
71
+ def flush(v_flush)
72
+ if v_flush != Z_NO_FLUSH
73
+ @z.zstream_run('', 0, flush)
74
+ end
75
+ @z.zstream_detach_buffer()
76
+ end
77
+
78
+ def params(level = Z_DEFAULT_COMPRESSION, strategy = Z_DEFAULT_STRATEGY)
79
+ err = deflateParams(@z.stream, level, strategy)
80
+ while err == Z_BUF_ERROR
81
+ warn('deflateParams() returned Z_BUF_ERROR')
82
+ @z.zstream_expand_buffer()
83
+ err = deflateParams(@z.stream, level, strategy)
84
+ end
85
+ if err != Z_OK
86
+ raise_zlib_error(err, @z.stream.msg)
87
+ end
88
+
89
+ nil
90
+ end
91
+
92
+ def set_dictionary(dic)
93
+ err = deflateSetDictionary(@z.stream, dic, dic.length)
94
+ if err != Z_OK
95
+ raise_zlib_error(err, @z.stream.msg)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zlib
4
+ class Error < StandardError
5
+ end
6
+
7
+ class StreamEnd < Error
8
+ end
9
+
10
+ class NeedDict < Error
11
+ end
12
+
13
+ class DataError < Error
14
+ end
15
+
16
+ class StreamError < Error
17
+ end
18
+
19
+ class MemError < Error
20
+ end
21
+
22
+ class BufError < Error
23
+ end
24
+
25
+ class VersionError < Error
26
+ end
27
+ end
@@ -0,0 +1,315 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'zstream'
4
+ require_relative 'gzipfile_errors'
5
+
6
+ module Zlib
7
+ class GzipFile
8
+ GZ_MAGIC1 = 0x1f
9
+ GZ_MAGIC2 = 0x8b
10
+ GZ_METHOD_DEFLATE = 8
11
+ GZ_FLAG_MULTIPART = 0x2
12
+ GZ_FLAG_EXTRA = 0x4
13
+ GZ_FLAG_ORIG_NAME = 0x8
14
+ GZ_FLAG_COMMENT = 0x10
15
+ GZ_FLAG_ENCRYPT = 0x20
16
+ GZ_FLAG_UNKNOWN_MASK = 0xc0
17
+
18
+ GZ_EXTRAFLAG_FAST = 0x4
19
+ GZ_EXTRAFLAG_SLOW = 0x2
20
+
21
+ OS_CODE = 0x03 # OS_UNIX
22
+
23
+ GZFILE_FLAG_SYNC = 0x10 # ZSTREAM_FLAG_UNUSED
24
+ GZFILE_FLAG_HEADER_FINISHED = (0x10 << 1) # (ZSTREAM_FLAG_UNUSED << 1)
25
+ GZFILE_FLAG_FOOTER_FINISHED = (0x10 << 2) # (ZSTREAM_FLAG_UNUSED << 2)
26
+
27
+ def GZFILE_IS_FINISHED(gz)
28
+ gz.z.ZSTREAM_IS_FINISHED() && (gz.z.buf.nil? || gz.z.buf.offset.zero?)
29
+ end
30
+
31
+ GZFILE_READ_SIZE = 2048
32
+
33
+ Gzfile = Struct.new(:z, :io, :level, :mtime, :os_code, :orig_name, :comment, :crc, :lineno, :ungetc, :end)
34
+
35
+ def gzfile_close(closeflag)
36
+ io = @gz.io
37
+ send(@gz.end)
38
+
39
+ @gz.io = nil
40
+ @gz.orig_name = nil
41
+ @gz.comment = nil
42
+
43
+ if closeflag && defined?(io.close)
44
+ io.close
45
+ end
46
+ end
47
+
48
+ def gzfile_ensure_close
49
+ if @gz.z.ZSTREAM_IS_READY()
50
+ gzfile_close(true)
51
+ end
52
+ nil
53
+ end
54
+
55
+ def self.wrap(io, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY)
56
+ obj = new(io, level, strategy)
57
+ if block_given?
58
+ begin
59
+ yield(obj)
60
+ ensure
61
+ obj.gzfile_ensure_close()
62
+ end
63
+ else
64
+ obj
65
+ end
66
+ end
67
+
68
+ def to_io
69
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
70
+ @gz.io
71
+ end
72
+
73
+ def crc
74
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
75
+ @gz.crc
76
+ end
77
+
78
+ def mtime
79
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
80
+ Time.at(@gz.mtime)
81
+ end
82
+
83
+ def level
84
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
85
+ @gz.level
86
+ end
87
+
88
+ def os_code
89
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
90
+ @gz.os_code
91
+ end
92
+
93
+ def orig_name
94
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
95
+ @gz.orig_name ? @gz.orig_name.dup : nil
96
+ end
97
+
98
+ def comment
99
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
100
+ @gz.comment ? @gz.comment.dup : nil
101
+ end
102
+
103
+ def close
104
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
105
+ gzfile_close(true)
106
+ @gz.io
107
+ end
108
+
109
+ def finish
110
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
111
+ gzfile_close(false)
112
+ @gz.io
113
+ end
114
+
115
+ def closed?
116
+ @gz.io.nil?
117
+ end
118
+
119
+ def sync
120
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
121
+ !(@gz.z.flags & GZFILE_FLAG_SYNC).zero?
122
+ end
123
+
124
+ def sync=(mode)
125
+ raise GzipFile::Error, 'closed gzip stream' unless @gz.z.ZSTREAM_IS_READY()
126
+ if mode
127
+ @gz.z.flags |= GZFILE_FLAG_SYNC
128
+ else
129
+ @gz.z.flags &= ~GZFILE_FLAG_SYNC
130
+ end
131
+ mode
132
+ end
133
+
134
+ def self.gzfile_s_open(filename, mode, level, strategy, &blk)
135
+ io = File.open(filename, mode)
136
+ self.wrap(io, level, strategy, &blk)
137
+ end
138
+
139
+ private
140
+
141
+ def gzfile_new(funcs, endfunc)
142
+ @gz = Gzfile.new
143
+ @gz.z = ZStream.new
144
+ @gz.z.zstream_init(funcs)
145
+ @gz.io = nil
146
+ @gz.level = 0
147
+ @gz.mtime = 0
148
+ @gz.os_code = OS_CODE
149
+ @gz.orig_name = nil
150
+ @gz.comment = nil
151
+ @gz.crc = crc32(0, nil, 0)
152
+ @gz.lineno = 0
153
+ @gz.ungetc = 0
154
+ @gz.end = endfunc
155
+ self
156
+ end
157
+
158
+ def gzfile_reset
159
+ @gz.z.zstream_reset
160
+ @gz.crc = crc32(0, nil, 0)
161
+ @gz.lineno = 0
162
+ @gz.ungetc = 0
163
+ end
164
+
165
+ def gzfile_get16(src)
166
+ src.unpack('v').first
167
+ end
168
+
169
+ def gzfile_get32(src)
170
+ src.unpack('V').first
171
+ end
172
+
173
+ def gzfile_set32(n)
174
+ [n].pack('V')
175
+ end
176
+
177
+ def gzfile_make_header
178
+ buf = 0.chr * 10
179
+ flags = 0
180
+ extraflags = 0
181
+ if @gz.orig_name
182
+ flags |= GZ_FLAG_ORIG_NAME
183
+ end
184
+ if @gz.comment
185
+ flags |= GZ_FLAG_COMMENT
186
+ end
187
+ if @gz.mtime.zero?
188
+ @gz.mtime = Time.now.to_i
189
+ end
190
+ if @gz.level == Zlib::BEST_SPEED
191
+ extraflags |= GZ_EXTRAFLAG_FAST
192
+ elsif @gz.level == Zlib::BEST_COMPRESSION
193
+ extraflags |= GZ_EXTRAFLAG_SLOW
194
+ end
195
+ buf[0] = GZ_MAGIC1.chr
196
+ buf[1] = GZ_MAGIC2.chr
197
+ buf[2] = GZ_METHOD_DEFLATE.chr
198
+ buf[3] = flags.chr
199
+ buf[4, 4] = gzfile_set32(@gz.mtime)
200
+ buf[8] = extraflags.chr
201
+ buf[9] = @gz.os_code.chr
202
+ @gz.z.zstream_append_buffer(buf, buf.length)
203
+
204
+ if @gz.orig_name
205
+ @gz.z.zstream_append_buffer(@gz.orig_name, @gz.orig_name.length)
206
+ @gz.z.zstream_append_buffer("\0", 1)
207
+ end
208
+ if @gz.comment
209
+ @gz.z.zstream_append_buffer(@gz.comment, @gz.comment.length)
210
+ @gz.z.zstream_append_buffer("\0", 1)
211
+ end
212
+
213
+ @gz.z.flags |= GZFILE_FLAG_HEADER_FINISHED
214
+ end
215
+
216
+ def gzfile_make_footer
217
+ buf = 0.chr * 8
218
+ buf[0, 4] = gzfile_set32(@gz.crc)
219
+ buf[4, 4] = gzfile_set32(@gz.z.stream.total_in)
220
+ @gz.z.zstream_append_buffer(buf, buf.length)
221
+ @gz.z.flags |= GZFILE_FLAG_FOOTER_FINISHED
222
+ end
223
+
224
+ def gzfile_read_header
225
+ if !gzfile_read_raw_ensure(10)
226
+ raise GzipFile::Error, 'not in gzip format'
227
+ end
228
+
229
+ head = @gz.z.input
230
+
231
+ if head[0].ord != GZ_MAGIC1 || head[1].ord != GZ_MAGIC2
232
+ raise GzipFile::Error, 'not in gzip format'
233
+ end
234
+ if head[2].ord != GZ_METHOD_DEFLATE
235
+ raise GzipFile::Error, "unsupported compression method #{head[2].ord}"
236
+ end
237
+
238
+ flags = head[3].ord
239
+ if (flags & GZ_FLAG_MULTIPART).nonzero?
240
+ raise GzipFile::Error, 'multi-part gzip file is not supported'
241
+ elsif (flags & GZ_FLAG_ENCRYPT).nonzero?
242
+ raise GzipFile::Error, 'encrypted gzip file is not supported'
243
+ elsif (flags & GZ_FLAG_UNKNOWN_MASK).nonzero?
244
+ raise GzipFile::Error, 'unknown flags 0x%02x' % flags
245
+ end
246
+
247
+ if (head[8].ord & GZ_EXTRAFLAG_FAST).nonzero?
248
+ @gz.level = Zlib::BEST_SPEED
249
+ elsif (head[8].ord & GZ_EXTRAFLAG_SLOW).nonzero?
250
+ @gz.level = Zlib::BEST_COMPRESSION
251
+ else
252
+ @gz.level = Zlib::DEFAULT_COMPRESSION
253
+ end
254
+
255
+ @gz.mtime = gzfile_get32(head[4, 4])
256
+ @gz.os_code = head[9].ord
257
+ @gz.z.zstream_discard_input(10)
258
+
259
+ if (flags & GZ_FLAG_EXTRA).nonzero?
260
+ if !gzfile_read_raw_ensure(2)
261
+ raise GzipFile::Error, 'unexpected end of file'
262
+ end
263
+ len = gzfile_get16(@gz.z.input)
264
+ if !gzfile_read_raw_ensure(2 + len)
265
+ raise GzipFile::Error, 'unexpected end of file'
266
+ end
267
+ @gz.z.zstream_discard_input(2 + len)
268
+ end
269
+ if (flags & GZ_FLAG_ORIG_NAME).nonzero?
270
+ ap = gzfile_read_raw_until_zero(0)
271
+ len = ap
272
+ @gz.orig_name = @gz.z.input[0, len]
273
+ @gz.z.zstream_discard_input(len + 1)
274
+ end
275
+ if (flags & GZ_FLAG_COMMENT).nonzero?
276
+ ap = gzfile_read_raw_until_zero(0)
277
+ len = ap
278
+ @gz.comment = @gz.z.input[0, len]
279
+ @gz.z.zstream_discard_input(len + 1)
280
+ end
281
+
282
+ if @gz.z.input && @gz.z.input.length > 0
283
+ @gz.z.zstream_run(0, 0, Zlib::SYNC_FLUSH)
284
+ end
285
+ end
286
+
287
+ def gzfile_check_footer
288
+ @gz.z.flags |= GZFILE_FLAG_FOOTER_FINISHED
289
+
290
+ if !gzfile_read_raw_ensure(8)
291
+ raise NoFooter, 'footer is not found'
292
+ end
293
+ crc = gzfile_get32(@gz.z.input)
294
+ length = gzfile_get32(@gz.z.input[4, 4])
295
+ @gz.z.stream.total_in += 8
296
+ @gz.z.zstream_discard_input(8)
297
+ if @gz.crc != crc
298
+ raise CRCError, 'invalid compressed data -- crc error'
299
+ end
300
+ if @gz.z.stream.total_out != length
301
+ raise LengthError, 'invalid compressed data -- length error'
302
+ end
303
+ end
304
+
305
+ def gzfile_calc_crc(str)
306
+ if str.length <= @gz.ungetc
307
+ @gz.ungetc -= str.length
308
+ else
309
+ @gz.crc = crc32(@gz.crc, str[@gz.ungetc, str.length - @gz.ungetc],
310
+ str.length - @gz.ungetc)
311
+ @gz.ungetc = 0
312
+ end
313
+ end
314
+ end
315
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors'
4
+
5
+ module Zlib
6
+ class GzipFile
7
+ class Error < Zlib::Error
8
+ end
9
+
10
+ class NoFooter < Error
11
+ end
12
+
13
+ class CRCError < Error
14
+ end
15
+
16
+ class LengthError < Error
17
+ end
18
+ end
19
+ end