rubysl-zlib 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/zlib/extconf.rb +65 -0
  7. data/ext/rubysl/zlib/zlib.c +3562 -0
  8. data/lib/rubysl/zlib.rb +2 -0
  9. data/lib/{rubysl-zlib → rubysl/zlib}/version.rb +1 -1
  10. data/lib/zlib.rb +1 -0
  11. data/rubysl-zlib.gemspec +20 -17
  12. data/spec/adler32_spec.rb +45 -0
  13. data/spec/crc32_spec.rb +51 -0
  14. data/spec/crc_table_spec.rb +10 -0
  15. data/spec/deflate/append_spec.rb +0 -0
  16. data/spec/deflate/deflate_spec.rb +49 -0
  17. data/spec/deflate/flush_spec.rb +0 -0
  18. data/spec/deflate/initialize_copy_spec.rb +0 -0
  19. data/spec/deflate/new_spec.rb +0 -0
  20. data/spec/deflate/params_spec.rb +19 -0
  21. data/spec/deflate/set_dictionary_spec.rb +14 -0
  22. data/spec/gzipfile/close_spec.rb +22 -0
  23. data/spec/gzipfile/closed_spec.rb +16 -0
  24. data/spec/gzipfile/comment_spec.rb +26 -0
  25. data/spec/gzipfile/crc_spec.rb +0 -0
  26. data/spec/gzipfile/finish_spec.rb +0 -0
  27. data/spec/gzipfile/level_spec.rb +0 -0
  28. data/spec/gzipfile/mtime_spec.rb +0 -0
  29. data/spec/gzipfile/orig_name_spec.rb +26 -0
  30. data/spec/gzipfile/os_code_spec.rb +0 -0
  31. data/spec/gzipfile/sync_spec.rb +0 -0
  32. data/spec/gzipfile/to_io_spec.rb +0 -0
  33. data/spec/gzipfile/wrap_spec.rb +0 -0
  34. data/spec/gzipreader/each_byte_spec.rb +32 -0
  35. data/spec/gzipreader/each_line_spec.rb +0 -0
  36. data/spec/gzipreader/each_spec.rb +0 -0
  37. data/spec/gzipreader/eof_spec.rb +54 -0
  38. data/spec/gzipreader/getc_spec.rb +54 -0
  39. data/spec/gzipreader/gets_spec.rb +0 -0
  40. data/spec/gzipreader/lineno_spec.rb +0 -0
  41. data/spec/gzipreader/new_spec.rb +0 -0
  42. data/spec/gzipreader/open_spec.rb +0 -0
  43. data/spec/gzipreader/pos_spec.rb +25 -0
  44. data/spec/gzipreader/read_spec.rb +68 -0
  45. data/spec/gzipreader/readchar_spec.rb +0 -0
  46. data/spec/gzipreader/readline_spec.rb +0 -0
  47. data/spec/gzipreader/readlines_spec.rb +0 -0
  48. data/spec/gzipreader/rewind_spec.rb +46 -0
  49. data/spec/gzipreader/tell_spec.rb +0 -0
  50. data/spec/gzipreader/ungetc_spec.rb +0 -0
  51. data/spec/gzipreader/unused_spec.rb +0 -0
  52. data/spec/gzipwriter/append_spec.rb +16 -0
  53. data/spec/gzipwriter/comment_spec.rb +0 -0
  54. data/spec/gzipwriter/flush_spec.rb +0 -0
  55. data/spec/gzipwriter/mtime_spec.rb +40 -0
  56. data/spec/gzipwriter/new_spec.rb +0 -0
  57. data/spec/gzipwriter/open_spec.rb +0 -0
  58. data/spec/gzipwriter/orig_name_spec.rb +0 -0
  59. data/spec/gzipwriter/pos_spec.rb +0 -0
  60. data/spec/gzipwriter/print_spec.rb +0 -0
  61. data/spec/gzipwriter/printf_spec.rb +0 -0
  62. data/spec/gzipwriter/putc_spec.rb +0 -0
  63. data/spec/gzipwriter/puts_spec.rb +0 -0
  64. data/spec/gzipwriter/tell_spec.rb +0 -0
  65. data/spec/gzipwriter/write_spec.rb +36 -0
  66. data/spec/inflate/append_spec.rb +60 -0
  67. data/spec/inflate/inflate_spec.rb +109 -0
  68. data/spec/inflate/new_spec.rb +0 -0
  69. data/spec/inflate/set_dictionary_spec.rb +19 -0
  70. data/spec/inflate/sync_point_spec.rb +0 -0
  71. data/spec/inflate/sync_spec.rb +0 -0
  72. data/spec/zlib_version_spec.rb +0 -0
  73. data/spec/zstream/adler_spec.rb +10 -0
  74. data/spec/zstream/avail_in_spec.rb +8 -0
  75. data/spec/zstream/avail_out_spec.rb +8 -0
  76. data/spec/zstream/close_spec.rb +0 -0
  77. data/spec/zstream/closed_spec.rb +0 -0
  78. data/spec/zstream/data_type_spec.rb +8 -0
  79. data/spec/zstream/end_spec.rb +0 -0
  80. data/spec/zstream/ended_spec.rb +0 -0
  81. data/spec/zstream/finish_spec.rb +0 -0
  82. data/spec/zstream/finished_spec.rb +0 -0
  83. data/spec/zstream/flush_next_in_spec.rb +0 -0
  84. data/spec/zstream/flush_next_out_spec.rb +15 -0
  85. data/spec/zstream/reset_spec.rb +0 -0
  86. data/spec/zstream/stream_end_spec.rb +0 -0
  87. data/spec/zstream/total_in_spec.rb +0 -0
  88. data/spec/zstream/total_out_spec.rb +0 -0
  89. metadata +224 -89
  90. data/lib/rubysl-zlib.rb +0 -7
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3e35918c7c26a7224d849fd5ef42ad8d2d455bef
4
+ data.tar.gz: 2d6ff132bdfb564c684b2c8f63d254b1189fe726
5
+ SHA512:
6
+ metadata.gz: 17c9b8ff98abdef73262767de28db076347d4bab27735c63b32f4c3f2fc15a5c77fcea4383804f0a2a5723a2172ed1b974eae790123df86db68327bedfda5cce
7
+ data.tar.gz: da471fa350b80e376efb5c5a1e7cb16e6f7c43c43fd73aac4d89895baf550be2499d419eaa973b0f025dcd9f9c788c55b5068340770088d6197c21831c2f32fa
data/.gitignore CHANGED
@@ -15,4 +15,3 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- .rbx
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ env:
3
+ - RUBYLIB=lib
4
+ script: bundle exec mspec
5
+ rvm:
6
+ - 1.8.7
7
+ - rbx-nightly-18mode
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RubySL::Zlib
1
+ # Rubysl::Zlib
2
2
 
3
3
  TODO: Write a gem description
4
4
 
@@ -24,6 +24,6 @@ TODO: Write usage instructions here
24
24
 
25
25
  1. Fork it
26
26
  2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Added some feature'`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
28
  4. Push to the branch (`git push origin my-new-feature`)
29
29
  5. Create new Pull Request
data/Rakefile CHANGED
@@ -1,2 +1 @@
1
- #!/usr/bin/env rake
2
1
  require "bundler/gem_tasks"
@@ -0,0 +1,65 @@
1
+ #
2
+ # extconf.rb
3
+ #
4
+ # $Id: extconf.rb 16679 2008-05-29 11:23:36Z knu $
5
+ #
6
+
7
+ require 'mkmf'
8
+ require 'rbconfig'
9
+
10
+ dir_config 'zlib'
11
+
12
+
13
+ if %w'z libz zlib1 zlib zdll'.find {|z| have_library(z, 'deflateReset')} and
14
+ have_header('zlib.h') then
15
+
16
+ defines = []
17
+
18
+ message 'checking for kind of operating system... '
19
+ os_code = with_config('os-code') ||
20
+ case RUBY_PLATFORM.split('-',2)[1]
21
+ when 'amigaos' then
22
+ os_code = 'AMIGA'
23
+ when /\Aos2[\-_]emx\z/ then
24
+ os_code = 'OS2'
25
+ when /mswin|mingw|bccwin/ then
26
+ # NOTE: cygwin should be regarded as Unix.
27
+ os_code = 'WIN32'
28
+ else
29
+ os_code = 'UNIX'
30
+ end
31
+ os_code = 'OS_' + os_code.upcase
32
+
33
+ OS_NAMES = {
34
+ 'OS_MSDOS' => 'MS-DOS',
35
+ 'OS_AMIGA' => 'Amiga',
36
+ 'OS_VMS' => 'VMS',
37
+ 'OS_UNIX' => 'Unix',
38
+ 'OS_ATARI' => 'Atari',
39
+ 'OS_OS2' => 'OS/2',
40
+ 'OS_MACOS' => 'MacOS',
41
+ 'OS_TOPS20' => 'TOPS20',
42
+ 'OS_WIN32' => 'Win32',
43
+ 'OS_VMCMS' => 'VM/CMS',
44
+ 'OS_ZSYSTEM' => 'Z-System',
45
+ 'OS_CPM' => 'CP/M',
46
+ 'OS_QDOS' => 'QDOS',
47
+ 'OS_RISCOS' => 'RISCOS',
48
+ 'OS_UNKNOWN' => 'Unknown',
49
+ }
50
+ unless OS_NAMES.key? os_code then
51
+ puts "invalid OS_CODE `#{os_code}'"
52
+ exit
53
+ end
54
+ message "#{OS_NAMES[os_code]}\n"
55
+ defines << "OS_CODE=#{os_code}"
56
+
57
+ $CFLAGS += " -Wno-pointer-sign"
58
+
59
+ $defs.concat(defines.collect{|d|' -D'+d})
60
+
61
+ have_type('z_crc_t', 'zlib.h')
62
+
63
+ create_makefile('zlib')
64
+
65
+ end
@@ -0,0 +1,3562 @@
1
+ /*
2
+ * zlib.c - An interface for zlib.
3
+ *
4
+ * Copyright (C) UENO Katsuhiro 2000-2003
5
+ *
6
+ * $Id: zlib.c 31714 2011-05-23 04:49:42Z shyouhei $
7
+ */
8
+
9
+ #define RSTRING_NOT_MODIFIED 1
10
+
11
+ #include <ruby.h>
12
+ #include <zlib.h>
13
+ #include <time.h>
14
+
15
+ #define RUBY_ZLIB_VERSION "0.6.0"
16
+
17
+
18
+ #define OBJ_IS_FREED(val) (RBASIC(val)->flags == 0)
19
+
20
+ #ifndef GZIP_SUPPORT
21
+ #define GZIP_SUPPORT 1
22
+ #endif
23
+
24
+ /* from zutil.h */
25
+ #ifndef DEF_MEM_LEVEL
26
+ #if MAX_MEM_LEVEL >= 8
27
+ #define DEF_MEM_LEVEL 8
28
+ #else
29
+ #define DEF_MEM_LEVEL MAX_MEM_LEVEL
30
+ #endif
31
+ #endif
32
+
33
+
34
+ /*--------- Prototypes --------*/
35
+
36
+ static NORETURN(void raise_zlib_error _((int, const char *)));
37
+ static VALUE rb_zlib_version _((VALUE));
38
+ static VALUE do_checksum _((int, VALUE*, uLong (*) _((uLong, const Bytef*, uInt))));
39
+ static VALUE rb_zlib_adler32 _((int, VALUE*, VALUE));
40
+ static VALUE rb_zlib_crc32 _((int, VALUE*, VALUE));
41
+ static VALUE rb_zlib_crc_table _((VALUE));
42
+ static voidpf zlib_mem_alloc _((voidpf, uInt, uInt));
43
+ static void zlib_mem_free _((voidpf, voidpf));
44
+ static void finalizer_warn _((const char*));
45
+
46
+ struct zstream;
47
+ struct zstream_funcs;
48
+ static void zstream_init _((struct zstream*, const struct zstream_funcs *));
49
+ static void zstream_expand_buffer _((struct zstream*));
50
+ static void zstream_expand_buffer_into _((struct zstream*, int));
51
+ static void zstream_append_buffer _((struct zstream*, const char*, int));
52
+ static VALUE zstream_detach_buffer _((struct zstream*));
53
+ static VALUE zstream_shift_buffer _((struct zstream*, int));
54
+ static void zstream_buffer_ungetc _((struct zstream*, int));
55
+ static void zstream_append_input _((struct zstream*, const char*, unsigned int));
56
+ static void zstream_discard_input _((struct zstream*, unsigned int));
57
+ static void zstream_reset_input _((struct zstream*));
58
+ static void zstream_passthrough_input _((struct zstream*));
59
+ static VALUE zstream_detach_input _((struct zstream*));
60
+ static void zstream_reset _((struct zstream*));
61
+ static VALUE zstream_end _((struct zstream*));
62
+ static void zstream_run _((struct zstream*, Bytef*, uInt, int));
63
+ static VALUE zstream_sync _((struct zstream*, Bytef*, uInt));
64
+ static void zstream_mark _((struct zstream*));
65
+ static void zstream_free _((struct zstream*));
66
+ static VALUE zstream_new _((VALUE, const struct zstream_funcs*));
67
+ static struct zstream *get_zstream _((VALUE));
68
+ static void zstream_finalize _((struct zstream*));
69
+
70
+ static VALUE rb_zstream_end _((VALUE));
71
+ static VALUE rb_zstream_reset _((VALUE));
72
+ static VALUE rb_zstream_finish _((VALUE));
73
+ static VALUE rb_zstream_flush_next_in _((VALUE));
74
+ static VALUE rb_zstream_flush_next_out _((VALUE));
75
+ static VALUE rb_zstream_avail_out _((VALUE));
76
+ static VALUE rb_zstream_set_avail_out _((VALUE, VALUE));
77
+ static VALUE rb_zstream_avail_in _((VALUE));
78
+ static VALUE rb_zstream_total_in _((VALUE));
79
+ static VALUE rb_zstream_total_out _((VALUE));
80
+ static VALUE rb_zstream_data_type _((VALUE));
81
+ static VALUE rb_zstream_adler _((VALUE));
82
+ static VALUE rb_zstream_finished_p _((VALUE));
83
+ static VALUE rb_zstream_closed_p _((VALUE));
84
+
85
+ static VALUE rb_deflate_s_allocate _((VALUE));
86
+ static VALUE rb_deflate_initialize _((int, VALUE*, VALUE));
87
+ static VALUE rb_deflate_init_copy _((VALUE, VALUE));
88
+ static VALUE deflate_run _((VALUE));
89
+ static VALUE rb_deflate_s_deflate _((int, VALUE*, VALUE));
90
+ static void do_deflate _((struct zstream*, VALUE, int));
91
+ static VALUE rb_deflate_deflate _((int, VALUE*, VALUE));
92
+ static VALUE rb_deflate_addstr _((VALUE, VALUE));
93
+ static VALUE rb_deflate_flush _((int, VALUE*, VALUE));
94
+ static VALUE rb_deflate_params _((VALUE, VALUE, VALUE));
95
+ static VALUE rb_deflate_set_dictionary _((VALUE, VALUE));
96
+
97
+ static VALUE inflate_run _((VALUE));
98
+ static VALUE rb_inflate_s_allocate _((VALUE));
99
+ static VALUE rb_inflate_initialize _((int, VALUE*, VALUE));
100
+ static VALUE rb_inflate_s_inflate _((VALUE, VALUE));
101
+ static void do_inflate _((struct zstream*, VALUE));
102
+ static VALUE rb_inflate_inflate _((VALUE, VALUE));
103
+ static VALUE rb_inflate_addstr _((VALUE, VALUE));
104
+ static VALUE rb_inflate_sync _((VALUE, VALUE));
105
+ static VALUE rb_inflate_sync_point_p _((VALUE));
106
+ static VALUE rb_inflate_set_dictionary _((VALUE, VALUE));
107
+
108
+ #if GZIP_SUPPORT
109
+ struct gzfile;
110
+ static void gzfile_mark _((struct gzfile*));
111
+ static void gzfile_free _((struct gzfile*));
112
+ static VALUE gzfile_new _((VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*))));
113
+ static void gzfile_reset _((struct gzfile*));
114
+ static void gzfile_close _((struct gzfile*, int));
115
+ static void gzfile_write_raw _((struct gzfile*));
116
+ static VALUE gzfile_read_raw _((struct gzfile*));
117
+ static int gzfile_read_raw_ensure _((struct gzfile*, int));
118
+ static char *gzfile_read_raw_until_zero _((struct gzfile*, long));
119
+ static unsigned int gzfile_get16 _((const unsigned char*));
120
+ static unsigned long gzfile_get32 _((const unsigned char*));
121
+ static void gzfile_set32 _((unsigned long n, unsigned char*));
122
+ static void gzfile_make_header _((struct gzfile*));
123
+ static void gzfile_make_footer _((struct gzfile*));
124
+ static void gzfile_read_header _((struct gzfile*));
125
+ static void gzfile_check_footer _((struct gzfile*));
126
+ static void gzfile_write _((struct gzfile*, Bytef*, uInt));
127
+ static long gzfile_read_more _((struct gzfile*));
128
+ static void gzfile_calc_crc _((struct gzfile*, VALUE));
129
+ static VALUE gzfile_read _((struct gzfile*, int));
130
+ static VALUE gzfile_read_all _((struct gzfile*));
131
+ static void gzfile_ungetc _((struct gzfile*, int));
132
+ static VALUE gzfile_writer_end_run _((VALUE));
133
+ static void gzfile_writer_end _((struct gzfile*));
134
+ static VALUE gzfile_reader_end_run _((VALUE));
135
+ static void gzfile_reader_end _((struct gzfile*));
136
+ static void gzfile_reader_rewind _((struct gzfile*));
137
+ static VALUE gzfile_reader_get_unused _((struct gzfile*));
138
+ static struct gzfile *get_gzfile _((VALUE));
139
+ static VALUE gzfile_ensure_close _((VALUE));
140
+ static VALUE rb_gzfile_s_wrap _((int, VALUE*, VALUE));
141
+ static VALUE gzfile_s_open _((int, VALUE*, VALUE, const char*));
142
+
143
+ static VALUE rb_gzfile_to_io _((VALUE));
144
+ static VALUE rb_gzfile_crc _((VALUE));
145
+ static VALUE rb_gzfile_mtime _((VALUE));
146
+ static VALUE rb_gzfile_level _((VALUE));
147
+ static VALUE rb_gzfile_os_code _((VALUE));
148
+ static VALUE rb_gzfile_orig_name _((VALUE));
149
+ static VALUE rb_gzfile_comment _((VALUE));
150
+ static VALUE rb_gzfile_lineno _((VALUE));
151
+ static VALUE rb_gzfile_set_lineno _((VALUE, VALUE));
152
+ static VALUE rb_gzfile_set_mtime _((VALUE, VALUE));
153
+ static VALUE rb_gzfile_set_orig_name _((VALUE, VALUE));
154
+ static VALUE rb_gzfile_set_comment _((VALUE, VALUE));
155
+ static VALUE rb_gzfile_close _((VALUE));
156
+ static VALUE rb_gzfile_finish _((VALUE));
157
+ static VALUE rb_gzfile_closed_p _((VALUE));
158
+ static VALUE rb_gzfile_eof_p _((VALUE));
159
+ static VALUE rb_gzfile_sync _((VALUE));
160
+ static VALUE rb_gzfile_set_sync _((VALUE, VALUE));
161
+ static VALUE rb_gzfile_total_in _((VALUE));
162
+ static VALUE rb_gzfile_total_out _((VALUE));
163
+
164
+ static VALUE rb_gzwriter_s_allocate _((VALUE));
165
+ static VALUE rb_gzwriter_s_open _((int, VALUE*, VALUE));
166
+ static VALUE rb_gzwriter_initialize _((int, VALUE*, VALUE));
167
+ static VALUE rb_gzwriter_flush _((int, VALUE*, VALUE));
168
+ static VALUE rb_gzwriter_write _((VALUE, VALUE));
169
+ static VALUE rb_gzwriter_putc _((VALUE, VALUE));
170
+
171
+ static VALUE rb_gzreader_s_allocate _((VALUE));
172
+ static VALUE rb_gzreader_s_open _((int, VALUE*, VALUE));
173
+ static VALUE rb_gzreader_initialize _((VALUE, VALUE));
174
+ static VALUE rb_gzreader_rewind _((VALUE));
175
+ static VALUE rb_gzreader_unused _((VALUE));
176
+ static VALUE rb_gzreader_read _((int, VALUE*, VALUE));
177
+ static VALUE rb_gzreader_getc _((VALUE));
178
+ static VALUE rb_gzreader_readchar _((VALUE));
179
+ static VALUE rb_gzreader_each_byte _((VALUE));
180
+ static VALUE rb_gzreader_ungetc _((VALUE, VALUE));
181
+ static void gzreader_skip_linebreaks _((struct gzfile*));
182
+ static VALUE gzreader_gets _((int, VALUE*, VALUE));
183
+ static VALUE rb_gzreader_gets _((int, VALUE*, VALUE));
184
+ static VALUE rb_gzreader_readline _((int, VALUE*, VALUE));
185
+ static VALUE rb_gzreader_each _((int, VALUE*, VALUE));
186
+ static VALUE rb_gzreader_readlines _((int, VALUE*, VALUE));
187
+ #endif /* GZIP_SUPPORT */
188
+
189
+
190
+ void Init_zlib _((void));
191
+
192
+
193
+
194
+ /*--------- Exceptions --------*/
195
+
196
+ static VALUE cZError, cStreamEnd, cNeedDict;
197
+ static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
198
+
199
+ static void
200
+ raise_zlib_error(err, msg)
201
+ int err;
202
+ const char *msg;
203
+ {
204
+ VALUE exc;
205
+
206
+ if (!msg) {
207
+ msg = zError(err);
208
+ }
209
+
210
+ switch(err) {
211
+ case Z_STREAM_END:
212
+ exc = rb_exc_new2(cStreamEnd, msg);
213
+ break;
214
+ case Z_NEED_DICT:
215
+ exc = rb_exc_new2(cNeedDict, msg);
216
+ break;
217
+ case Z_STREAM_ERROR:
218
+ exc = rb_exc_new2(cStreamError, msg);
219
+ break;
220
+ case Z_DATA_ERROR:
221
+ exc = rb_exc_new2(cDataError, msg);
222
+ break;
223
+ case Z_BUF_ERROR:
224
+ exc = rb_exc_new2(cBufError, msg);
225
+ break;
226
+ case Z_VERSION_ERROR:
227
+ exc = rb_exc_new2(cVersionError, msg);
228
+ break;
229
+ case Z_MEM_ERROR:
230
+ exc = rb_exc_new2(cMemError, msg);
231
+ break;
232
+ case Z_ERRNO:
233
+ rb_sys_fail(msg);
234
+ /* no return */
235
+ default:
236
+ {
237
+ char buf[BUFSIZ];
238
+ snprintf(buf, BUFSIZ, "unknown zlib error %d: %s", err, msg);
239
+ exc = rb_exc_new2(cZError, buf);
240
+ }
241
+ }
242
+
243
+ rb_exc_raise(exc);
244
+ }
245
+
246
+
247
+ /*--- Warning (in finalizer) ---*/
248
+
249
+ static void
250
+ finalizer_warn(msg)
251
+ const char *msg;
252
+ {
253
+ fprintf(stderr, "zlib(finalizer): %s\n", msg);
254
+ }
255
+
256
+
257
+ /*-------- module Zlib --------*/
258
+
259
+ /*
260
+ * Returns the string which represents the version of zlib library.
261
+ */
262
+ static VALUE
263
+ rb_zlib_version(klass)
264
+ VALUE klass;
265
+ {
266
+ VALUE str;
267
+
268
+ str = rb_str_new2(zlibVersion());
269
+ OBJ_TAINT(str); /* for safe */
270
+ return str;
271
+ }
272
+
273
+ static VALUE
274
+ do_checksum(argc, argv, func)
275
+ int argc;
276
+ VALUE *argv;
277
+ uLong (*func) _((uLong, const Bytef *, uInt));
278
+ {
279
+ VALUE str, vsum;
280
+ unsigned long sum;
281
+
282
+ rb_scan_args(argc, argv, "02", &str, &vsum);
283
+
284
+ if (!NIL_P(vsum)) {
285
+ sum = NUM2ULONG(vsum);
286
+ }
287
+ else if (NIL_P(str)) {
288
+ sum = 0;
289
+ }
290
+ else {
291
+ sum = func(0, Z_NULL, 0);
292
+ }
293
+
294
+ if (NIL_P(str)) {
295
+ sum = func(sum, Z_NULL, 0);
296
+ }
297
+ else {
298
+ StringValue(str);
299
+ sum = func(sum, RSTRING(str)->ptr, RSTRING(str)->len);
300
+ }
301
+ return rb_uint2inum(sum);
302
+ }
303
+
304
+ /*
305
+ * call-seq: Zlib.adler32(string, adler)
306
+ *
307
+ * Calculates Adler-32 checksum for +string+, and returns updated value of
308
+ * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
309
+ * +adler+ is omitted, it assumes that the initial value is given to +adler+.
310
+ *
311
+ * FIXME: expression.
312
+ */
313
+ static VALUE
314
+ rb_zlib_adler32(argc, argv, klass)
315
+ int argc;
316
+ VALUE *argv;
317
+ VALUE klass;
318
+ {
319
+ return do_checksum(argc, argv, adler32);
320
+ }
321
+
322
+ /*
323
+ * call-seq: Zlib.crc32(string, adler)
324
+ *
325
+ * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
326
+ * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
327
+ * assumes that the initial value is given to +crc+.
328
+ *
329
+ * FIXME: expression.
330
+ */
331
+ static VALUE
332
+ rb_zlib_crc32(argc, argv, klass)
333
+ int argc;
334
+ VALUE *argv;
335
+ VALUE klass;
336
+ {
337
+ return do_checksum(argc, argv, crc32);
338
+ }
339
+
340
+ /*
341
+ * Returns the table for calculating CRC checksum as an array.
342
+ */
343
+ static VALUE
344
+ rb_zlib_crc_table(obj)
345
+ VALUE obj;
346
+ {
347
+ #if !defined(HAVE_TYPE_Z_CRC_T)
348
+ /* z_crc_t is defined since zlib-1.2.7. */
349
+ typedef unsigned long z_crc_t;
350
+ #endif
351
+ const z_crc_t *crctbl;
352
+ VALUE dst;
353
+ int i;
354
+
355
+ crctbl = get_crc_table();
356
+ dst = rb_ary_new2(256);
357
+
358
+ for (i = 0; i < 256; i++) {
359
+ rb_ary_push(dst, rb_uint2inum(crctbl[i]));
360
+ }
361
+ return dst;
362
+ }
363
+
364
+
365
+
366
+ /*-------- zstream - internal APIs --------*/
367
+
368
+ struct zstream {
369
+ unsigned long flags;
370
+ VALUE buf;
371
+ long buf_filled;
372
+ VALUE input;
373
+ z_stream stream;
374
+ const struct zstream_funcs {
375
+ int (*reset) _((z_streamp));
376
+ int (*end) _((z_streamp));
377
+ int (*run) _((z_streamp, int));
378
+ } *func;
379
+ };
380
+
381
+ #define ZSTREAM_FLAG_READY 0x1
382
+ #define ZSTREAM_FLAG_IN_STREAM 0x2
383
+ #define ZSTREAM_FLAG_FINISHED 0x4
384
+ #define ZSTREAM_FLAG_CLOSING 0x8
385
+ #define ZSTREAM_FLAG_UNUSED 0x10
386
+
387
+ #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
388
+ #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
389
+ #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
390
+ #define ZSTREAM_IS_CLOSING(z) ((z)->flags & ZSTREAM_FLAG_CLOSING)
391
+
392
+ /* I think that more better value should be found,
393
+ but I gave up finding it. B) */
394
+ #define ZSTREAM_INITIAL_BUFSIZE 1024
395
+ #define ZSTREAM_AVAIL_OUT_STEP_MAX 16384
396
+ #define ZSTREAM_AVAIL_OUT_STEP_MIN 2048
397
+
398
+ static const struct zstream_funcs deflate_funcs = {
399
+ deflateReset, deflateEnd, deflate,
400
+ };
401
+
402
+ static const struct zstream_funcs inflate_funcs = {
403
+ inflateReset, inflateEnd, inflate,
404
+ };
405
+
406
+
407
+ static voidpf
408
+ zlib_mem_alloc(opaque, items, size)
409
+ voidpf opaque;
410
+ uInt items, size;
411
+ {
412
+ return xmalloc(items * size);
413
+ }
414
+
415
+ static void
416
+ zlib_mem_free(opaque, address)
417
+ voidpf opaque, address;
418
+ {
419
+ free(address);
420
+ }
421
+
422
+ static void
423
+ zstream_init(z, func)
424
+ struct zstream *z;
425
+ const struct zstream_funcs *func;
426
+ {
427
+ z->flags = 0;
428
+ z->buf = Qnil;
429
+ z->buf_filled = 0;
430
+ z->input = Qnil;
431
+ z->stream.zalloc = zlib_mem_alloc;
432
+ z->stream.zfree = zlib_mem_free;
433
+ z->stream.opaque = Z_NULL;
434
+ z->stream.msg = Z_NULL;
435
+ z->stream.next_in = Z_NULL;
436
+ z->stream.avail_in = 0;
437
+ z->stream.next_out = Z_NULL;
438
+ z->stream.avail_out = 0;
439
+ z->func = func;
440
+ }
441
+
442
+ #define zstream_init_deflate(z) zstream_init((z), &deflate_funcs)
443
+ #define zstream_init_inflate(z) zstream_init((z), &inflate_funcs)
444
+
445
+ static void
446
+ zstream_expand_buffer(z)
447
+ struct zstream *z;
448
+ {
449
+ long inc;
450
+
451
+ if (NIL_P(z->buf)) {
452
+ /* I uses rb_str_new here not rb_str_buf_new because
453
+ rb_str_buf_new makes a zero-length string. */
454
+ z->buf = rb_str_new(0, ZSTREAM_INITIAL_BUFSIZE);
455
+ z->buf_filled = 0;
456
+ z->stream.next_out = RSTRING(z->buf)->ptr;
457
+ z->stream.avail_out = ZSTREAM_INITIAL_BUFSIZE;
458
+ return;
459
+ }
460
+
461
+ if (RSTRING(z->buf)->len - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
462
+ /* to keep other threads from freezing */
463
+ z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
464
+ }
465
+ else {
466
+ inc = z->buf_filled / 2;
467
+ if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
468
+ inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
469
+ }
470
+ rb_str_resize(z->buf, z->buf_filled + inc);
471
+ z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
472
+ inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
473
+ }
474
+ z->stream.next_out = RSTRING(z->buf)->ptr + z->buf_filled;
475
+ }
476
+
477
+ static void
478
+ zstream_expand_buffer_into(z, size)
479
+ struct zstream *z;
480
+ int size;
481
+ {
482
+ if (NIL_P(z->buf)) {
483
+ /* I uses rb_str_new here not rb_str_buf_new because
484
+ rb_str_buf_new makes a zero-length string. */
485
+ z->buf = rb_str_new(0, size);
486
+ z->buf_filled = 0;
487
+ z->stream.next_out = RSTRING(z->buf)->ptr;
488
+ z->stream.avail_out = size;
489
+ }
490
+ else if (z->stream.avail_out != size) {
491
+ rb_str_resize(z->buf, z->buf_filled + size);
492
+ z->stream.next_out = RSTRING(z->buf)->ptr + z->buf_filled;
493
+ z->stream.avail_out = size;
494
+ }
495
+ }
496
+
497
+ static void
498
+ zstream_append_buffer(z, src, len)
499
+ struct zstream *z;
500
+ const char *src;
501
+ int len;
502
+ {
503
+ if (NIL_P(z->buf)) {
504
+ z->buf = rb_str_buf_new(len);
505
+ rb_str_buf_cat(z->buf, src, len);
506
+ z->buf_filled = len;
507
+ z->stream.next_out = RSTRING(z->buf)->ptr;
508
+ z->stream.avail_out = 0;
509
+ return;
510
+ }
511
+
512
+ if (RSTRING(z->buf)->len < z->buf_filled + len) {
513
+ rb_str_resize(z->buf, z->buf_filled + len);
514
+ z->stream.avail_out = 0;
515
+ }
516
+ else {
517
+ if (z->stream.avail_out >= len) {
518
+ z->stream.avail_out -= len;
519
+ }
520
+ else {
521
+ z->stream.avail_out = 0;
522
+ }
523
+ }
524
+ memcpy(RSTRING(z->buf)->ptr + z->buf_filled, src, len);
525
+ z->buf_filled += len;
526
+ z->stream.next_out = RSTRING(z->buf)->ptr + z->buf_filled;
527
+ }
528
+
529
+ #define zstream_append_buffer2(z,v) \
530
+ zstream_append_buffer((z),RSTRING(v)->ptr,RSTRING(v)->len)
531
+
532
+ static VALUE
533
+ zstream_detach_buffer(z)
534
+ struct zstream *z;
535
+ {
536
+ VALUE dst;
537
+
538
+ if (NIL_P(z->buf)) {
539
+ dst = rb_str_new(0, 0);
540
+ }
541
+ else {
542
+ dst = z->buf;
543
+ rb_str_resize(dst, z->buf_filled);
544
+ }
545
+
546
+ z->buf = Qnil;
547
+ z->buf_filled = 0;
548
+ z->stream.next_out = 0;
549
+ z->stream.avail_out = 0;
550
+ return dst;
551
+ }
552
+
553
+ static VALUE
554
+ zstream_shift_buffer(z, len)
555
+ struct zstream *z;
556
+ int len;
557
+ {
558
+ VALUE dst;
559
+
560
+ if (z->buf_filled <= len) {
561
+ return zstream_detach_buffer(z);
562
+ }
563
+
564
+ dst = rb_str_substr(z->buf, 0, len);
565
+ z->buf_filled -= len;
566
+ memmove(RSTRING(z->buf)->ptr, RSTRING(z->buf)->ptr + len,
567
+ z->buf_filled);
568
+ z->stream.next_out = RSTRING(z->buf)->ptr + z->buf_filled;
569
+ z->stream.avail_out = RSTRING(z->buf)->len - z->buf_filled;
570
+ if (z->stream.avail_out > ZSTREAM_AVAIL_OUT_STEP_MAX) {
571
+ z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
572
+ }
573
+
574
+ return dst;
575
+ }
576
+
577
+ static void
578
+ zstream_buffer_ungetc(z, c)
579
+ struct zstream *z;
580
+ int c;
581
+ {
582
+ if (NIL_P(z->buf) || RSTRING(z->buf)->len - z->buf_filled == 0) {
583
+ zstream_expand_buffer(z);
584
+ }
585
+
586
+ memmove(RSTRING(z->buf)->ptr + 1, RSTRING(z->buf)->ptr, z->buf_filled);
587
+ RSTRING(z->buf)->ptr[0] = (char)c;
588
+ z->buf_filled++;
589
+ if (z->stream.avail_out > 0) {
590
+ z->stream.next_out++;
591
+ z->stream.avail_out--;
592
+ }
593
+ }
594
+
595
+ static void
596
+ zstream_append_input(z, src, len)
597
+ struct zstream *z;
598
+ const char *src;
599
+ unsigned int len;
600
+ {
601
+ if (len <= 0) return;
602
+
603
+ if (NIL_P(z->input)) {
604
+ z->input = rb_str_buf_new(len);
605
+ rb_str_buf_cat(z->input, src, len);
606
+ }
607
+ else {
608
+ rb_str_buf_cat(z->input, src, len);
609
+ }
610
+ }
611
+
612
+ #define zstream_append_input2(z,v)\
613
+ RB_GC_GUARD(v),\
614
+ zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
615
+
616
+ static void
617
+ zstream_discard_input(z, len)
618
+ struct zstream *z;
619
+ unsigned int len;
620
+ {
621
+ if (NIL_P(z->input) || RSTRING(z->input)->len <= len) {
622
+ z->input = Qnil;
623
+ }
624
+ else {
625
+ memmove(RSTRING(z->input)->ptr, RSTRING(z->input)->ptr + len,
626
+ RSTRING(z->input)->len - len);
627
+ rb_str_resize(z->input, RSTRING(z->input)->len - len);
628
+ }
629
+ }
630
+
631
+ static void
632
+ zstream_reset_input(z)
633
+ struct zstream *z;
634
+ {
635
+ z->input = Qnil;
636
+ }
637
+
638
+ static void
639
+ zstream_passthrough_input(z)
640
+ struct zstream *z;
641
+ {
642
+ if (!NIL_P(z->input)) {
643
+ zstream_append_buffer2(z, z->input);
644
+ z->input = Qnil;
645
+ }
646
+ }
647
+
648
+ static VALUE
649
+ zstream_detach_input(z)
650
+ struct zstream *z;
651
+ {
652
+ VALUE dst;
653
+
654
+ if (NIL_P(z->input)) {
655
+ dst = rb_str_new(0, 0);
656
+ }
657
+ else {
658
+ dst = z->input;
659
+ }
660
+ z->input = Qnil;
661
+ return dst;
662
+ }
663
+
664
+ static void
665
+ zstream_reset(z)
666
+ struct zstream *z;
667
+ {
668
+ int err;
669
+
670
+ err = z->func->reset(&z->stream);
671
+ if (err != Z_OK) {
672
+ raise_zlib_error(err, z->stream.msg);
673
+ }
674
+ z->flags = ZSTREAM_FLAG_READY;
675
+ z->buf = Qnil;
676
+ z->buf_filled = 0;
677
+ z->stream.next_out = 0;
678
+ z->stream.avail_out = 0;
679
+ zstream_reset_input(z);
680
+ }
681
+
682
+ static VALUE
683
+ zstream_end(z)
684
+ struct zstream *z;
685
+ {
686
+ int err;
687
+
688
+ if (!ZSTREAM_IS_READY(z)) {
689
+ rb_warning("attempt to close uninitialized zstream; ignored.");
690
+ return Qnil;
691
+ }
692
+ if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
693
+ rb_warning("attempt to close unfinished zstream; reset forced.");
694
+ zstream_reset(z);
695
+ }
696
+
697
+ zstream_reset_input(z);
698
+ err = z->func->end(&z->stream);
699
+ if (err != Z_OK) {
700
+ raise_zlib_error(err, z->stream.msg);
701
+ }
702
+ z->flags = 0;
703
+ return Qnil;
704
+ }
705
+
706
+ static void
707
+ zstream_run(z, src, len, flush)
708
+ struct zstream *z;
709
+ Bytef *src;
710
+ uInt len;
711
+ int flush;
712
+ {
713
+ uInt n;
714
+ int err;
715
+ volatile VALUE guard;
716
+
717
+ if (NIL_P(z->input) && len == 0) {
718
+ z->stream.next_in = "";
719
+ z->stream.avail_in = 0;
720
+ }
721
+ else {
722
+ zstream_append_input(z, src, len);
723
+ z->stream.next_in = RSTRING(z->input)->ptr;
724
+ z->stream.avail_in = RSTRING(z->input)->len;
725
+ /* keep reference to `z->input' so as not to be garbage collected
726
+ after zstream_reset_input() and prevent `z->stream.next_in'
727
+ from dangling. */
728
+ guard = z->input;
729
+ }
730
+
731
+ if (z->stream.avail_out == 0) {
732
+ zstream_expand_buffer(z);
733
+ }
734
+
735
+ for (;;) {
736
+ /* VC allocates err and guard to same address. accessing err and guard
737
+ in same scope prevents it. */
738
+ RB_GC_GUARD(guard);
739
+ n = z->stream.avail_out;
740
+ err = z->func->run(&z->stream, flush);
741
+ z->buf_filled += n - z->stream.avail_out;
742
+ rb_thread_schedule();
743
+
744
+ if (err == Z_STREAM_END) {
745
+ z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
746
+ z->flags |= ZSTREAM_FLAG_FINISHED;
747
+ break;
748
+ }
749
+ if (err != Z_OK) {
750
+ if (flush != Z_FINISH && err == Z_BUF_ERROR
751
+ && z->stream.avail_out > 0) {
752
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
753
+ break;
754
+ }
755
+ zstream_reset_input(z);
756
+ if (z->stream.avail_in > 0) {
757
+ zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
758
+ }
759
+ raise_zlib_error(err, z->stream.msg);
760
+ }
761
+ if (z->stream.avail_out > 0) {
762
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
763
+ break;
764
+ }
765
+ zstream_expand_buffer(z);
766
+ }
767
+
768
+ zstream_reset_input(z);
769
+ if (z->stream.avail_in > 0) {
770
+ zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
771
+ guard = Qnil; /* prevent tail call to make guard effective */
772
+ }
773
+ }
774
+
775
+ static VALUE
776
+ zstream_sync(z, src, len)
777
+ struct zstream *z;
778
+ Bytef *src;
779
+ uInt len;
780
+ {
781
+ VALUE rest;
782
+ int err;
783
+
784
+ if (!NIL_P(z->input)) {
785
+ z->stream.next_in = RSTRING(z->input)->ptr;
786
+ z->stream.avail_in = RSTRING(z->input)->len;
787
+ err = inflateSync(&z->stream);
788
+ if (err == Z_OK) {
789
+ zstream_discard_input(z,
790
+ RSTRING(z->input)->len - z->stream.avail_in);
791
+ zstream_append_input(z, src, len);
792
+ return Qtrue;
793
+ }
794
+ zstream_reset_input(z);
795
+ if (err != Z_DATA_ERROR) {
796
+ rest = rb_str_new(z->stream.next_in, z->stream.avail_in);
797
+ raise_zlib_error(err, z->stream.msg);
798
+ }
799
+ }
800
+
801
+ if (len <= 0) return Qfalse;
802
+
803
+ z->stream.next_in = src;
804
+ z->stream.avail_in = len;
805
+ err = inflateSync(&z->stream);
806
+ if (err == Z_OK) {
807
+ zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
808
+ return Qtrue;
809
+ }
810
+ if (err != Z_DATA_ERROR) {
811
+ rest = rb_str_new(z->stream.next_in, z->stream.avail_in);
812
+ raise_zlib_error(err, z->stream.msg);
813
+ }
814
+ return Qfalse;
815
+ }
816
+
817
+ static void
818
+ zstream_mark(z)
819
+ struct zstream *z;
820
+ {
821
+ rb_gc_mark(z->buf);
822
+ rb_gc_mark(z->input);
823
+ }
824
+
825
+ static void
826
+ zstream_finalize(z)
827
+ struct zstream *z;
828
+ {
829
+ int err = z->func->end(&z->stream);
830
+ if (err == Z_STREAM_ERROR)
831
+ finalizer_warn("the stream state was inconsistent.");
832
+ if (err == Z_DATA_ERROR)
833
+ finalizer_warn("the stream was freed prematurely.");
834
+ }
835
+
836
+ static void
837
+ zstream_free(z)
838
+ struct zstream *z;
839
+ {
840
+ if (ZSTREAM_IS_READY(z)) {
841
+ zstream_finalize(z);
842
+ }
843
+ free(z);
844
+ }
845
+
846
+ static VALUE
847
+ zstream_new(klass, funcs)
848
+ VALUE klass;
849
+ const struct zstream_funcs *funcs;
850
+ {
851
+ VALUE obj;
852
+ struct zstream *z;
853
+
854
+ obj = Data_Make_Struct(klass, struct zstream,
855
+ zstream_mark, zstream_free, z);
856
+ zstream_init(z, funcs);
857
+ return obj;
858
+ }
859
+
860
+ #define zstream_deflate_new(klass) zstream_new((klass), &deflate_funcs)
861
+ #define zstream_inflate_new(klass) zstream_new((klass), &inflate_funcs)
862
+
863
+ static struct zstream *
864
+ get_zstream(obj)
865
+ VALUE obj;
866
+ {
867
+ struct zstream *z;
868
+
869
+ Data_Get_Struct(obj, struct zstream, z);
870
+ if (!ZSTREAM_IS_READY(z)) {
871
+ rb_raise(cZError, "stream is not ready");
872
+ }
873
+ return z;
874
+ }
875
+
876
+
877
+ /* ------------------------------------------------------------------------- */
878
+
879
+ /*
880
+ * Document-class: Zlib::ZStream
881
+ *
882
+ * Zlib::ZStream is the abstract class for the stream which handles the
883
+ * compressed data. The operations are defined in the subclasses:
884
+ * Zlib::Deflate for compression, and Zlib::Inflate for decompression.
885
+ *
886
+ * An instance of Zlib::ZStream has one stream (struct zstream in the source)
887
+ * and two variable-length buffers which associated to the input (next_in) of
888
+ * the stream and the output (next_out) of the stream. In this document,
889
+ * "input buffer" means the buffer for input, and "output buffer" means the
890
+ * buffer for output.
891
+ *
892
+ * Data input into an instance of Zlib::ZStream are temporally stored into
893
+ * the end of input buffer, and then data in input buffer are processed from
894
+ * the beginning of the buffer until no more output from the stream is
895
+ * produced (i.e. until avail_out > 0 after processing). During processing,
896
+ * output buffer is allocated and expanded automatically to hold all output
897
+ * data.
898
+ *
899
+ * Some particular instance methods consume the data in output buffer and
900
+ * return them as a String.
901
+ *
902
+ * Here is an ascii art for describing above:
903
+ *
904
+ * +================ an instance of Zlib::ZStream ================+
905
+ * || ||
906
+ * || +--------+ +-------+ +--------+ ||
907
+ * || +--| output |<---------|zstream|<---------| input |<--+ ||
908
+ * || | | buffer | next_out+-------+next_in | buffer | | ||
909
+ * || | +--------+ +--------+ | ||
910
+ * || | | ||
911
+ * +===|======================================================|===+
912
+ * | |
913
+ * v |
914
+ * "output data" "input data"
915
+ *
916
+ * If an error occurs during processing input buffer, an exception which is a
917
+ * subclass of Zlib::Error is raised. At that time, both input and output
918
+ * buffer keep their conditions at the time when the error occurs.
919
+ *
920
+ * == Method Catalogue
921
+ *
922
+ * Many of the methods in this class are fairly low-level and unlikely to be
923
+ * of interest to users. In fact, users are unlikely to use this class
924
+ * directly; rather they will be interested in Zlib::Inflate and
925
+ * Zlib::Deflate.
926
+ *
927
+ * The higher level methods are listed below.
928
+ *
929
+ * - #total_in
930
+ * - #total_out
931
+ * - #data_type
932
+ * - #adler
933
+ * - #reset
934
+ * - #finish
935
+ * - #finished?
936
+ * - #close
937
+ * - #closed?
938
+ */
939
+
940
+ /*
941
+ * Closes the stream. All operations on the closed stream will raise an
942
+ * exception.
943
+ */
944
+ static VALUE
945
+ rb_zstream_end(obj)
946
+ VALUE obj;
947
+ {
948
+ zstream_end(get_zstream(obj));
949
+ return Qnil;
950
+ }
951
+
952
+ /*
953
+ * Resets and initializes the stream. All data in both input and output buffer
954
+ * are discarded.
955
+ */
956
+ static VALUE
957
+ rb_zstream_reset(obj)
958
+ VALUE obj;
959
+ {
960
+ zstream_reset(get_zstream(obj));
961
+ return Qnil;
962
+ }
963
+
964
+ /*
965
+ * Finishes the stream and flushes output buffer. See Zlib::Deflate#finish and
966
+ * Zlib::Inflate#finish for details of this behavior.
967
+ */
968
+ static VALUE
969
+ rb_zstream_finish(obj)
970
+ VALUE obj;
971
+ {
972
+ struct zstream *z = get_zstream(obj);
973
+ VALUE dst;
974
+
975
+ zstream_run(z, "", 0, Z_FINISH);
976
+ dst = zstream_detach_buffer(z);
977
+
978
+ OBJ_INFECT(dst, obj);
979
+ return dst;
980
+ }
981
+
982
+ /*
983
+ * Flushes input buffer and returns all data in that buffer.
984
+ */
985
+ static VALUE
986
+ rb_zstream_flush_next_in(obj)
987
+ VALUE obj;
988
+ {
989
+ struct zstream *z;
990
+ VALUE dst;
991
+
992
+ Data_Get_Struct(obj, struct zstream, z);
993
+ dst = zstream_detach_input(z);
994
+ OBJ_INFECT(dst, obj);
995
+ return dst;
996
+ }
997
+
998
+ /*
999
+ * Flushes output buffer and returns all data in that buffer.
1000
+ */
1001
+ static VALUE
1002
+ rb_zstream_flush_next_out(obj)
1003
+ VALUE obj;
1004
+ {
1005
+ struct zstream *z;
1006
+ VALUE dst;
1007
+
1008
+ Data_Get_Struct(obj, struct zstream, z);
1009
+ dst = zstream_detach_buffer(z);
1010
+ OBJ_INFECT(dst, obj);
1011
+ return dst;
1012
+ }
1013
+
1014
+ /*
1015
+ * Returns number of bytes of free spaces in output buffer. Because the free
1016
+ * space is allocated automatically, this method returns 0 normally.
1017
+ */
1018
+ static VALUE
1019
+ rb_zstream_avail_out(obj)
1020
+ VALUE obj;
1021
+ {
1022
+ struct zstream *z;
1023
+ Data_Get_Struct(obj, struct zstream, z);
1024
+ return rb_uint2inum(z->stream.avail_out);
1025
+ }
1026
+
1027
+ /*
1028
+ * Allocates +size+ bytes of free space in the output buffer. If there are more
1029
+ * than +size+ bytes already in the buffer, the buffer is truncated. Because
1030
+ * free space is allocated automatically, you usually don't need to use this
1031
+ * method.
1032
+ */
1033
+ static VALUE
1034
+ rb_zstream_set_avail_out(obj, size)
1035
+ VALUE obj, size;
1036
+ {
1037
+ struct zstream *z = get_zstream(obj);
1038
+
1039
+ Check_Type(size, T_FIXNUM);
1040
+ zstream_expand_buffer_into(z, FIX2INT(size));
1041
+ return size;
1042
+ }
1043
+
1044
+ /*
1045
+ * Returns bytes of data in the input buffer. Normally, returns 0.
1046
+ */
1047
+ static VALUE
1048
+ rb_zstream_avail_in(obj)
1049
+ VALUE obj;
1050
+ {
1051
+ struct zstream *z;
1052
+ Data_Get_Struct(obj, struct zstream, z);
1053
+ return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING(z->input)->len));
1054
+ }
1055
+
1056
+ /*
1057
+ * Returns the total bytes of the input data to the stream. FIXME
1058
+ */
1059
+ static VALUE
1060
+ rb_zstream_total_in(obj)
1061
+ VALUE obj;
1062
+ {
1063
+ return rb_uint2inum(get_zstream(obj)->stream.total_in);
1064
+ }
1065
+
1066
+ /*
1067
+ * Returns the total bytes of the output data from the stream. FIXME
1068
+ */
1069
+ static VALUE
1070
+ rb_zstream_total_out(obj)
1071
+ VALUE obj;
1072
+ {
1073
+ return rb_uint2inum(get_zstream(obj)->stream.total_out);
1074
+ }
1075
+
1076
+ /*
1077
+ * Guesses the type of the data which have been inputed into the stream. The
1078
+ * returned value is either <tt>Zlib::BINARY</tt>, <tt>Zlib::ASCII</tt>, or
1079
+ * <tt>Zlib::UNKNOWN</tt>.
1080
+ */
1081
+ static VALUE
1082
+ rb_zstream_data_type(obj)
1083
+ VALUE obj;
1084
+ {
1085
+ return INT2FIX(get_zstream(obj)->stream.data_type);
1086
+ }
1087
+
1088
+ /*
1089
+ * Returns the adler-32 checksum.
1090
+ */
1091
+ static VALUE
1092
+ rb_zstream_adler(obj)
1093
+ VALUE obj;
1094
+ {
1095
+ return rb_uint2inum(get_zstream(obj)->stream.adler);
1096
+ }
1097
+
1098
+ /*
1099
+ * Returns true if the stream is finished.
1100
+ */
1101
+ static VALUE
1102
+ rb_zstream_finished_p(obj)
1103
+ VALUE obj;
1104
+ {
1105
+ return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
1106
+ }
1107
+
1108
+ /*
1109
+ * Returns true if the stream is closed.
1110
+ */
1111
+ static VALUE
1112
+ rb_zstream_closed_p(obj)
1113
+ VALUE obj;
1114
+ {
1115
+ struct zstream *z;
1116
+ Data_Get_Struct(obj, struct zstream, z);
1117
+ return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
1118
+ }
1119
+
1120
+
1121
+ /* ------------------------------------------------------------------------- */
1122
+
1123
+ /*
1124
+ * Document-class: Zlib::Deflate
1125
+ *
1126
+ * Zlib::Deflate is the class for compressing data. See Zlib::Stream for more
1127
+ * information.
1128
+ */
1129
+
1130
+ #define FIXNUMARG(val, ifnil) \
1131
+ (NIL_P((val)) ? (ifnil) \
1132
+ : ((void)Check_Type((val), T_FIXNUM), FIX2INT((val))))
1133
+
1134
+ #define ARG_LEVEL(val) FIXNUMARG((val), Z_DEFAULT_COMPRESSION)
1135
+ #define ARG_WBITS(val) FIXNUMARG((val), MAX_WBITS)
1136
+ #define ARG_MEMLEVEL(val) FIXNUMARG((val), DEF_MEM_LEVEL)
1137
+ #define ARG_STRATEGY(val) FIXNUMARG((val), Z_DEFAULT_STRATEGY)
1138
+ #define ARG_FLUSH(val) FIXNUMARG((val), Z_NO_FLUSH)
1139
+
1140
+
1141
+ static VALUE
1142
+ rb_deflate_s_allocate(klass)
1143
+ VALUE klass;
1144
+ {
1145
+ return zstream_deflate_new(klass);
1146
+ }
1147
+
1148
+ /*
1149
+ * call-seq: Zlib::Deflate.new(level=nil, windowBits=nil, memlevel=nil, strategy=nil)
1150
+ *
1151
+ * Creates a new deflate stream for compression. See zlib.h for details of
1152
+ * each argument. If an argument is nil, the default value of that argument is
1153
+ * used.
1154
+ *
1155
+ * TODO: document better!
1156
+ */
1157
+ static VALUE
1158
+ rb_deflate_initialize(argc, argv, obj)
1159
+ int argc;
1160
+ VALUE *argv;
1161
+ VALUE obj;
1162
+ {
1163
+ struct zstream *z;
1164
+ VALUE level, wbits, memlevel, strategy;
1165
+ int err;
1166
+
1167
+ rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
1168
+ Data_Get_Struct(obj, struct zstream, z);
1169
+
1170
+ err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
1171
+ ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
1172
+ ARG_STRATEGY(strategy));
1173
+ if (err != Z_OK) {
1174
+ raise_zlib_error(err, z->stream.msg);
1175
+ }
1176
+ ZSTREAM_READY(z);
1177
+
1178
+ return obj;
1179
+ }
1180
+
1181
+ /*
1182
+ * Duplicates the deflate stream.
1183
+ */
1184
+ static VALUE
1185
+ rb_deflate_init_copy(self, orig)
1186
+ VALUE self, orig;
1187
+ {
1188
+ struct zstream *z1, *z2;
1189
+ int err;
1190
+
1191
+ Data_Get_Struct(self, struct zstream, z1);
1192
+ z2 = get_zstream(orig);
1193
+
1194
+ err = deflateCopy(&z1->stream, &z2->stream);
1195
+ if (err != Z_OK) {
1196
+ raise_zlib_error(err, 0);
1197
+ }
1198
+ z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
1199
+ z1->buf = NIL_P(z2->buf) ? Qnil : rb_str_dup(z2->buf);
1200
+ z1->buf_filled = z2->buf_filled;
1201
+ z1->flags = z2->flags;
1202
+
1203
+ return self;
1204
+ }
1205
+
1206
+ static VALUE
1207
+ deflate_run(args)
1208
+ VALUE args;
1209
+ {
1210
+ struct zstream *z = (struct zstream *)((VALUE *)args)[0];
1211
+ VALUE src = ((VALUE *)args)[1];
1212
+
1213
+ zstream_run(z, RSTRING(src)->ptr, RSTRING(src)->len, Z_FINISH);
1214
+ return zstream_detach_buffer(z);
1215
+ }
1216
+
1217
+ /*
1218
+ * call-seq: Zlib::Deflate.deflate(string[, level])
1219
+ *
1220
+ * Compresses the given +string+. Valid values of level are
1221
+ * <tt>Zlib::NO_COMPRESSION</tt>, <tt>Zlib::BEST_SPEED</tt>,
1222
+ * <tt>Zlib::BEST_COMPRESSION</tt>, <tt>Zlib::DEFAULT_COMPRESSION</tt>, and an
1223
+ * integer from 0 to 9.
1224
+ *
1225
+ * This method is almost equivalent to the following code:
1226
+ *
1227
+ * def deflate(string, level)
1228
+ * z = Zlib::Deflate.new(level)
1229
+ * dst = z.deflate(string, Zlib::FINISH)
1230
+ * z.close
1231
+ * dst
1232
+ * end
1233
+ *
1234
+ * TODO: what's default value of +level+?
1235
+ *
1236
+ */
1237
+ static VALUE
1238
+ rb_deflate_s_deflate(argc, argv, klass)
1239
+ int argc;
1240
+ VALUE *argv;
1241
+ VALUE klass;
1242
+ {
1243
+ struct zstream z;
1244
+ VALUE src, level, dst, args[2];
1245
+ int err, lev;
1246
+
1247
+ rb_scan_args(argc, argv, "11", &src, &level);
1248
+
1249
+ lev = ARG_LEVEL(level);
1250
+ StringValue(src);
1251
+ zstream_init_deflate(&z);
1252
+ err = deflateInit(&z.stream, lev);
1253
+ if (err != Z_OK) {
1254
+ raise_zlib_error(err, z.stream.msg);
1255
+ }
1256
+ ZSTREAM_READY(&z);
1257
+
1258
+ args[0] = (VALUE)&z;
1259
+ args[1] = src;
1260
+ dst = rb_ensure(deflate_run, (VALUE)args, zstream_end, (VALUE)&z);
1261
+
1262
+ OBJ_INFECT(dst, src);
1263
+ return dst;
1264
+ }
1265
+
1266
+ static void
1267
+ do_deflate(z, src, flush)
1268
+ struct zstream *z;
1269
+ VALUE src;
1270
+ int flush;
1271
+ {
1272
+ if (NIL_P(src)) {
1273
+ zstream_run(z, "", 0, Z_FINISH);
1274
+ return;
1275
+ }
1276
+ StringValue(src);
1277
+ if (flush != Z_NO_FLUSH || RSTRING(src)->len > 0) { /* prevent BUF_ERROR */
1278
+ zstream_run(z, RSTRING(src)->ptr, RSTRING(src)->len, flush);
1279
+ }
1280
+ }
1281
+
1282
+ /*
1283
+ * call-seq: deflate(string[, flush])
1284
+ *
1285
+ * Inputs +string+ into the deflate stream and returns the output from the
1286
+ * stream. On calling this method, both the input and the output buffers of
1287
+ * the stream are flushed. If +string+ is nil, this method finishes the
1288
+ * stream, just like Zlib::ZStream#finish.
1289
+ *
1290
+ * The value of +flush+ should be either <tt>Zlib::NO_FLUSH</tt>,
1291
+ * <tt>Zlib::SYNC_FLUSH</tt>, <tt>Zlib::FULL_FLUSH</tt>, or
1292
+ * <tt>Zlib::FINISH</tt>. See zlib.h for details.
1293
+ *
1294
+ * TODO: document better!
1295
+ */
1296
+ static VALUE
1297
+ rb_deflate_deflate(argc, argv, obj)
1298
+ int argc;
1299
+ VALUE *argv;
1300
+ VALUE obj;
1301
+ {
1302
+ struct zstream *z = get_zstream(obj);
1303
+ VALUE src, flush, dst;
1304
+
1305
+ rb_scan_args(argc, argv, "11", &src, &flush);
1306
+ OBJ_INFECT(obj, src);
1307
+ do_deflate(z, src, ARG_FLUSH(flush));
1308
+ dst = zstream_detach_buffer(z);
1309
+
1310
+ OBJ_INFECT(dst, obj);
1311
+ return dst;
1312
+ }
1313
+
1314
+ /*
1315
+ * call-seq: << string
1316
+ *
1317
+ * Inputs +string+ into the deflate stream just like Zlib::Deflate#deflate, but
1318
+ * returns the Zlib::Deflate object itself. The output from the stream is
1319
+ * preserved in output buffer.
1320
+ */
1321
+ static VALUE
1322
+ rb_deflate_addstr(obj, src)
1323
+ VALUE obj, src;
1324
+ {
1325
+ OBJ_INFECT(obj, src);
1326
+ do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
1327
+ return obj;
1328
+ }
1329
+
1330
+ /*
1331
+ * call-seq: flush(flush)
1332
+ *
1333
+ * This method is equivalent to <tt>deflate('', flush)</tt>. If flush is omitted,
1334
+ * <tt>Zlib::SYNC_FLUSH</tt> is used as flush. This method is just provided
1335
+ * to improve the readability of your Ruby program.
1336
+ *
1337
+ * TODO: document better!
1338
+ */
1339
+ static VALUE
1340
+ rb_deflate_flush(argc, argv, obj)
1341
+ int argc;
1342
+ VALUE *argv;
1343
+ VALUE obj;
1344
+ {
1345
+ struct zstream *z = get_zstream(obj);
1346
+ VALUE v_flush, dst;
1347
+ int flush;
1348
+
1349
+ rb_scan_args(argc, argv, "01", &v_flush);
1350
+ flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
1351
+ if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
1352
+ zstream_run(z, "", 0, flush);
1353
+ }
1354
+ dst = zstream_detach_buffer(z);
1355
+
1356
+ OBJ_INFECT(dst, obj);
1357
+ return dst;
1358
+ }
1359
+
1360
+ /*
1361
+ * call-seq: params(level, strategy)
1362
+ *
1363
+ * Changes the parameters of the deflate stream. See zlib.h for details. The
1364
+ * output from the stream by changing the params is preserved in output
1365
+ * buffer.
1366
+ *
1367
+ * TODO: document better!
1368
+ */
1369
+ static VALUE
1370
+ rb_deflate_params(obj, v_level, v_strategy)
1371
+ VALUE obj, v_level, v_strategy;
1372
+ {
1373
+ struct zstream *z = get_zstream(obj);
1374
+ int level, strategy;
1375
+ int err;
1376
+ uInt n;
1377
+
1378
+ level = ARG_LEVEL(v_level);
1379
+ strategy = ARG_STRATEGY(v_strategy);
1380
+
1381
+ n = z->stream.avail_out;
1382
+ err = deflateParams(&z->stream, level, strategy);
1383
+ z->buf_filled += n - z->stream.avail_out;
1384
+ while (err == Z_BUF_ERROR) {
1385
+ rb_warning("deflateParams() returned Z_BUF_ERROR");
1386
+ zstream_expand_buffer(z);
1387
+ n = z->stream.avail_out;
1388
+ err = deflateParams(&z->stream, level, strategy);
1389
+ z->buf_filled += n - z->stream.avail_out;
1390
+ }
1391
+ if (err != Z_OK) {
1392
+ raise_zlib_error(err, z->stream.msg);
1393
+ }
1394
+
1395
+ return Qnil;
1396
+ }
1397
+
1398
+ /*
1399
+ * call-seq: set_dictionary(string)
1400
+ *
1401
+ * Sets the preset dictionary and returns +string+. This method is available
1402
+ * just only after Zlib::Deflate.new or Zlib::ZStream#reset method was called.
1403
+ * See zlib.h for details.
1404
+ *
1405
+ * TODO: document better!
1406
+ */
1407
+ static VALUE
1408
+ rb_deflate_set_dictionary(obj, dic)
1409
+ VALUE obj, dic;
1410
+ {
1411
+ struct zstream *z = get_zstream(obj);
1412
+ VALUE src = dic;
1413
+ int err;
1414
+
1415
+ OBJ_INFECT(obj, dic);
1416
+ StringValue(src);
1417
+ err = deflateSetDictionary(&z->stream,
1418
+ RSTRING(src)->ptr, RSTRING(src)->len);
1419
+ if (err != Z_OK) {
1420
+ raise_zlib_error(err, z->stream.msg);
1421
+ }
1422
+
1423
+ return dic;
1424
+ }
1425
+
1426
+
1427
+ /* ------------------------------------------------------------------------- */
1428
+
1429
+ /*
1430
+ * Document-class: Zlib::Inflate
1431
+ *
1432
+ * Zlib:Inflate is the class for decompressing compressed data. Unlike
1433
+ * Zlib::Deflate, an instance of this class is not able to duplicate (clone,
1434
+ * dup) itself.
1435
+ */
1436
+
1437
+
1438
+
1439
+ static VALUE
1440
+ rb_inflate_s_allocate(klass)
1441
+ VALUE klass;
1442
+ {
1443
+ return zstream_inflate_new(klass);
1444
+ }
1445
+
1446
+ /*
1447
+ * call-seq: Zlib::Inflate.new(window_bits)
1448
+ *
1449
+ * Creates a new inflate stream for decompression. See zlib.h for details
1450
+ * of the argument. If +window_bits+ is +nil+, the default value is used.
1451
+ *
1452
+ * TODO: document better!
1453
+ */
1454
+ static VALUE
1455
+ rb_inflate_initialize(argc, argv, obj)
1456
+ int argc;
1457
+ VALUE *argv;
1458
+ VALUE obj;
1459
+ {
1460
+ struct zstream *z;
1461
+ VALUE wbits;
1462
+ int err;
1463
+
1464
+ rb_scan_args(argc, argv, "01", &wbits);
1465
+ Data_Get_Struct(obj, struct zstream, z);
1466
+
1467
+ err = inflateInit2(&z->stream, ARG_WBITS(wbits));
1468
+ if (err != Z_OK) {
1469
+ raise_zlib_error(err, z->stream.msg);
1470
+ }
1471
+ ZSTREAM_READY(z);
1472
+
1473
+ return obj;
1474
+ }
1475
+
1476
+ static VALUE
1477
+ inflate_run(args)
1478
+ VALUE args;
1479
+ {
1480
+ struct zstream *z = (struct zstream *)((VALUE *)args)[0];
1481
+ VALUE src = ((VALUE *)args)[1];
1482
+
1483
+ zstream_run(z, RSTRING(src)->ptr, RSTRING(src)->len, Z_SYNC_FLUSH);
1484
+ zstream_run(z, "", 0, Z_FINISH); /* for checking errors */
1485
+ return zstream_detach_buffer(z);
1486
+ }
1487
+
1488
+ /*
1489
+ * call-seq: Zlib::Inflate.inflate(string)
1490
+ *
1491
+ * Decompresses +string+. Raises a Zlib::NeedDict exception if a preset
1492
+ * dictionary is needed for decompression.
1493
+ *
1494
+ * This method is almost equivalent to the following code:
1495
+ *
1496
+ * def inflate(string)
1497
+ * zstream = Zlib::Inflate.new
1498
+ * buf = zstream.inflate(string)
1499
+ * zstream.finish
1500
+ * zstream.close
1501
+ * buf
1502
+ * end
1503
+ *
1504
+ */
1505
+ static VALUE
1506
+ rb_inflate_s_inflate(obj, src)
1507
+ VALUE obj, src;
1508
+ {
1509
+ struct zstream z;
1510
+ VALUE dst, args[2];
1511
+ int err;
1512
+
1513
+ StringValue(src);
1514
+ zstream_init_inflate(&z);
1515
+ err = inflateInit(&z.stream);
1516
+ if (err != Z_OK) {
1517
+ raise_zlib_error(err, z.stream.msg);
1518
+ }
1519
+ ZSTREAM_READY(&z);
1520
+
1521
+ args[0] = (VALUE)&z;
1522
+ args[1] = src;
1523
+ dst = rb_ensure(inflate_run, (VALUE)args, zstream_end, (VALUE)&z);
1524
+
1525
+ OBJ_INFECT(dst, src);
1526
+ return dst;
1527
+ }
1528
+
1529
+ static void
1530
+ do_inflate(z, src)
1531
+ struct zstream *z;
1532
+ VALUE src;
1533
+ {
1534
+ if (NIL_P(src)) {
1535
+ zstream_run(z, "", 0, Z_FINISH);
1536
+ return;
1537
+ }
1538
+ StringValue(src);
1539
+ if (RSTRING(src)->len > 0) { /* prevent Z_BUF_ERROR */
1540
+ zstream_run(z, RSTRING(src)->ptr, RSTRING(src)->len, Z_SYNC_FLUSH);
1541
+ }
1542
+ }
1543
+
1544
+ /*
1545
+ * call-seq: inflate(string)
1546
+ *
1547
+ * Inputs +string+ into the inflate stream and returns the output from the
1548
+ * stream. Calling this method, both the input and the output buffer of the
1549
+ * stream are flushed. If string is +nil+, this method finishes the stream,
1550
+ * just like Zlib::ZStream#finish.
1551
+ *
1552
+ * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
1553
+ * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
1554
+ * call this method again with an empty string. (<i>???</i>)
1555
+ *
1556
+ * TODO: document better!
1557
+ */
1558
+ static VALUE
1559
+ rb_inflate_inflate(obj, src)
1560
+ VALUE obj, src;
1561
+ {
1562
+ struct zstream *z = get_zstream(obj);
1563
+ VALUE dst;
1564
+
1565
+ OBJ_INFECT(obj, src);
1566
+
1567
+ if (ZSTREAM_IS_FINISHED(z)) {
1568
+ if (NIL_P(src)) {
1569
+ dst = zstream_detach_buffer(z);
1570
+ }
1571
+ else {
1572
+ StringValue(src);
1573
+ zstream_append_buffer2(z, src);
1574
+ dst = rb_str_new(0, 0);
1575
+ }
1576
+ }
1577
+ else {
1578
+ do_inflate(z, src);
1579
+ dst = zstream_detach_buffer(z);
1580
+ if (ZSTREAM_IS_FINISHED(z)) {
1581
+ zstream_passthrough_input(z);
1582
+ }
1583
+ }
1584
+
1585
+ OBJ_INFECT(dst, obj);
1586
+ return dst;
1587
+ }
1588
+
1589
+ /*
1590
+ * call-seq: << string
1591
+ *
1592
+ * Inputs +string+ into the inflate stream just like Zlib::Inflate#inflate, but
1593
+ * returns the Zlib::Inflate object itself. The output from the stream is
1594
+ * preserved in output buffer.
1595
+ */
1596
+ static VALUE
1597
+ rb_inflate_addstr(obj, src)
1598
+ VALUE obj, src;
1599
+ {
1600
+ struct zstream *z = get_zstream(obj);
1601
+
1602
+ OBJ_INFECT(obj, src);
1603
+
1604
+ if (ZSTREAM_IS_FINISHED(z)) {
1605
+ if (!NIL_P(src)) {
1606
+ StringValue(src);
1607
+ zstream_append_buffer2(z, src);
1608
+ }
1609
+ }
1610
+ else {
1611
+ do_inflate(z, src);
1612
+ if (ZSTREAM_IS_FINISHED(z)) {
1613
+ zstream_passthrough_input(z);
1614
+ }
1615
+ }
1616
+
1617
+ return obj;
1618
+ }
1619
+
1620
+ /*
1621
+ * call-seq: sync(string)
1622
+ *
1623
+ * Inputs +string+ into the end of input buffer and skips data until a full
1624
+ * flush point can be found. If the point is found in the buffer, this method
1625
+ * flushes the buffer and returns false. Otherwise it returns +true+ and the
1626
+ * following data of full flush point is preserved in the buffer.
1627
+ */
1628
+ static VALUE
1629
+ rb_inflate_sync(obj, src)
1630
+ VALUE obj, src;
1631
+ {
1632
+ struct zstream *z = get_zstream(obj);
1633
+
1634
+ OBJ_INFECT(obj, src);
1635
+ StringValue(src);
1636
+ return zstream_sync(z, RSTRING(src)->ptr, RSTRING(src)->len);
1637
+ }
1638
+
1639
+ /*
1640
+ * Quoted verbatim from original documentation:
1641
+ *
1642
+ * What is this?
1643
+ *
1644
+ * <tt>:)</tt>
1645
+ */
1646
+ static VALUE
1647
+ rb_inflate_sync_point_p(obj)
1648
+ VALUE obj;
1649
+ {
1650
+ struct zstream *z = get_zstream(obj);
1651
+ int err;
1652
+
1653
+ err = inflateSyncPoint(&z->stream);
1654
+ if (err == 1) {
1655
+ return Qtrue;
1656
+ }
1657
+ if (err != Z_OK) {
1658
+ raise_zlib_error(err, z->stream.msg);
1659
+ }
1660
+ return Qfalse;
1661
+ }
1662
+
1663
+ /*
1664
+ * Sets the preset dictionary and returns +string+. This method is available just
1665
+ * only after a Zlib::NeedDict exception was raised. See zlib.h for details.
1666
+ *
1667
+ * TODO: document better!
1668
+ */
1669
+ static VALUE
1670
+ rb_inflate_set_dictionary(obj, dic)
1671
+ VALUE obj, dic;
1672
+ {
1673
+ struct zstream *z = get_zstream(obj);
1674
+ VALUE src = dic;
1675
+ int err;
1676
+
1677
+ OBJ_INFECT(obj, dic);
1678
+ StringValue(src);
1679
+ err = inflateSetDictionary(&z->stream,
1680
+ RSTRING(src)->ptr, RSTRING(src)->len);
1681
+ if (err != Z_OK) {
1682
+ raise_zlib_error(err, z->stream.msg);
1683
+ }
1684
+
1685
+ return dic;
1686
+ }
1687
+
1688
+
1689
+
1690
+ #if GZIP_SUPPORT
1691
+
1692
+ /* NOTE: Features for gzip files of Ruby/zlib are written from scratch
1693
+ * and using undocumented feature of zlib, negative wbits.
1694
+ * I don't think gzFile APIs of zlib are good for Ruby.
1695
+ */
1696
+
1697
+ /*------- .gz file header --------*/
1698
+
1699
+ #define GZ_MAGIC1 0x1f
1700
+ #define GZ_MAGIC2 0x8b
1701
+ #define GZ_METHOD_DEFLATE 8
1702
+ #define GZ_FLAG_MULTIPART 0x2
1703
+ #define GZ_FLAG_EXTRA 0x4
1704
+ #define GZ_FLAG_ORIG_NAME 0x8
1705
+ #define GZ_FLAG_COMMENT 0x10
1706
+ #define GZ_FLAG_ENCRYPT 0x20
1707
+ #define GZ_FLAG_UNKNOWN_MASK 0xc0
1708
+
1709
+ #define GZ_EXTRAFLAG_FAST 0x4
1710
+ #define GZ_EXTRAFLAG_SLOW 0x2
1711
+
1712
+ /* from zutil.h */
1713
+ #define OS_MSDOS 0x00
1714
+ #define OS_AMIGA 0x01
1715
+ #define OS_VMS 0x02
1716
+ #define OS_UNIX 0x03
1717
+ #define OS_ATARI 0x05
1718
+ #define OS_OS2 0x06
1719
+ #define OS_MACOS 0x07
1720
+ #define OS_TOPS20 0x0a
1721
+ #define OS_WIN32 0x0b
1722
+
1723
+ #define OS_VMCMS 0x04
1724
+ #define OS_ZSYSTEM 0x08
1725
+ #define OS_CPM 0x09
1726
+ #define OS_QDOS 0x0c
1727
+ #define OS_RISCOS 0x0d
1728
+ #define OS_UNKNOWN 0xff
1729
+
1730
+ #ifndef OS_CODE
1731
+ #define OS_CODE OS_UNIX
1732
+ #endif
1733
+
1734
+ static ID id_write, id_read, id_flush, id_seek, id_close;
1735
+ static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
1736
+
1737
+
1738
+
1739
+ /*-------- gzfile internal APIs --------*/
1740
+
1741
+ struct gzfile {
1742
+ struct zstream z;
1743
+ VALUE io;
1744
+ int level;
1745
+ time_t mtime; /* for header */
1746
+ int os_code; /* for header */
1747
+ VALUE orig_name; /* for header; must be a String */
1748
+ VALUE comment; /* for header; must be a String */
1749
+ unsigned long crc;
1750
+ int lineno;
1751
+ int ungetc;
1752
+ void (*end)(struct gzfile *);
1753
+ };
1754
+
1755
+ #define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
1756
+ #define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
1757
+ #define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2)
1758
+
1759
+ #define GZFILE_IS_FINISHED(gz) \
1760
+ (ZSTREAM_IS_FINISHED(&gz->z) && (gz)->z.buf_filled == 0)
1761
+
1762
+ #define GZFILE_READ_SIZE 2048
1763
+
1764
+
1765
+ static void
1766
+ gzfile_mark(gz)
1767
+ struct gzfile *gz;
1768
+ {
1769
+ rb_gc_mark(gz->io);
1770
+ rb_gc_mark(gz->orig_name);
1771
+ rb_gc_mark(gz->comment);
1772
+ zstream_mark(&gz->z);
1773
+ }
1774
+
1775
+ static void
1776
+ gzfile_free(gz)
1777
+ struct gzfile *gz;
1778
+ {
1779
+ struct zstream *z = &gz->z;
1780
+
1781
+ if (ZSTREAM_IS_READY(z)) {
1782
+ if (z->func == &deflate_funcs) {
1783
+ finalizer_warn("Zlib::GzipWriter object must be closed explicitly.");
1784
+ }
1785
+ zstream_finalize(z);
1786
+ }
1787
+ free(gz);
1788
+ }
1789
+
1790
+ static VALUE
1791
+ gzfile_new(klass, funcs, endfunc)
1792
+ VALUE klass;
1793
+ const struct zstream_funcs *funcs;
1794
+ void (*endfunc) _((struct gzfile *));
1795
+ {
1796
+ VALUE obj;
1797
+ struct gzfile *gz;
1798
+
1799
+ obj = Data_Make_Struct(klass, struct gzfile, gzfile_mark, gzfile_free, gz);
1800
+ zstream_init(&gz->z, funcs);
1801
+ gz->io = Qnil;
1802
+ gz->level = 0;
1803
+ gz->mtime = 0;
1804
+ gz->os_code = OS_CODE;
1805
+ gz->orig_name = Qnil;
1806
+ gz->comment = Qnil;
1807
+ gz->crc = crc32(0, Z_NULL, 0);
1808
+ gz->lineno = 0;
1809
+ gz->ungetc = 0;
1810
+ gz->end = endfunc;
1811
+
1812
+ return obj;
1813
+ }
1814
+
1815
+ #define gzfile_writer_new(gz) gzfile_new((gz),&deflate_funcs,gzfile_writer_end)
1816
+ #define gzfile_reader_new(gz) gzfile_new((gz),&inflate_funcs,gzfile_reader_end)
1817
+
1818
+ static void
1819
+ gzfile_reset(gz)
1820
+ struct gzfile *gz;
1821
+ {
1822
+ zstream_reset(&gz->z);
1823
+ gz->crc = crc32(0, Z_NULL, 0);
1824
+ gz->lineno = 0;
1825
+ gz->ungetc = 0;
1826
+ }
1827
+
1828
+ static void
1829
+ gzfile_close(gz, closeflag)
1830
+ struct gzfile *gz;
1831
+ int closeflag;
1832
+ {
1833
+ VALUE io = gz->io;
1834
+
1835
+ gz->end(gz);
1836
+ gz->io = Qnil;
1837
+ gz->orig_name = Qnil;
1838
+ gz->comment = Qnil;
1839
+ if (closeflag && rb_respond_to(io, id_close)) {
1840
+ rb_funcall(io, id_close, 0);
1841
+ }
1842
+ }
1843
+
1844
+ static void
1845
+ gzfile_write_raw(gz)
1846
+ struct gzfile *gz;
1847
+ {
1848
+ VALUE str;
1849
+
1850
+ if (gz->z.buf_filled > 0) {
1851
+ str = zstream_detach_buffer(&gz->z);
1852
+ OBJ_TAINT(str); /* for safe */
1853
+ rb_funcall(gz->io, id_write, 1, str);
1854
+ if ((gz->z.flags & GZFILE_FLAG_SYNC)
1855
+ && rb_respond_to(gz->io, id_flush))
1856
+ rb_funcall(gz->io, id_flush, 0);
1857
+ }
1858
+ }
1859
+
1860
+ static VALUE
1861
+ gzfile_read_raw(gz)
1862
+ struct gzfile *gz;
1863
+ {
1864
+ VALUE str;
1865
+
1866
+ str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
1867
+ if (!NIL_P(str)) {
1868
+ Check_Type(str, T_STRING);
1869
+ }
1870
+ return str;
1871
+ }
1872
+
1873
+ static int
1874
+ gzfile_read_raw_ensure(gz, size)
1875
+ struct gzfile *gz;
1876
+ int size;
1877
+ {
1878
+ VALUE str;
1879
+
1880
+ while (NIL_P(gz->z.input) || RSTRING(gz->z.input)->len < size) {
1881
+ str = gzfile_read_raw(gz);
1882
+ if (NIL_P(str)) return Qfalse;
1883
+ zstream_append_input2(&gz->z, str);
1884
+ }
1885
+ return Qtrue;
1886
+ }
1887
+
1888
+ static char *
1889
+ gzfile_read_raw_until_zero(gz, offset)
1890
+ struct gzfile *gz;
1891
+ long offset;
1892
+ {
1893
+ VALUE str;
1894
+ char *p;
1895
+
1896
+ for (;;) {
1897
+ p = memchr(RSTRING(gz->z.input)->ptr + offset, '\0',
1898
+ RSTRING(gz->z.input)->len - offset);
1899
+ if (p) break;
1900
+ str = gzfile_read_raw(gz);
1901
+ if (NIL_P(str)) {
1902
+ rb_raise(cGzError, "unexpected end of file");
1903
+ }
1904
+ offset = RSTRING(gz->z.input)->len;
1905
+ zstream_append_input2(&gz->z, str);
1906
+ }
1907
+ return p;
1908
+ }
1909
+
1910
+ static unsigned int
1911
+ gzfile_get16(src)
1912
+ const unsigned char *src;
1913
+ {
1914
+ unsigned int n;
1915
+ n = *(src++) & 0xff;
1916
+ n |= (*(src++) & 0xff) << 8;
1917
+ return n;
1918
+ }
1919
+
1920
+ static unsigned long
1921
+ gzfile_get32(src)
1922
+ const unsigned char *src;
1923
+ {
1924
+ unsigned long n;
1925
+ n = *(src++) & 0xff;
1926
+ n |= (*(src++) & 0xff) << 8;
1927
+ n |= (*(src++) & 0xff) << 16;
1928
+ n |= (*(src++) & 0xffU) << 24;
1929
+ return n;
1930
+ }
1931
+
1932
+ static void
1933
+ gzfile_set32(n, dst)
1934
+ unsigned long n;
1935
+ unsigned char *dst;
1936
+ {
1937
+ *(dst++) = n & 0xff;
1938
+ *(dst++) = (n >> 8) & 0xff;
1939
+ *(dst++) = (n >> 16) & 0xff;
1940
+ *dst = (n >> 24) & 0xff;
1941
+ }
1942
+
1943
+ static void
1944
+ gzfile_make_header(gz)
1945
+ struct gzfile *gz;
1946
+ {
1947
+ unsigned char buf[10]; /* the size of gzip header */
1948
+ unsigned char flags = 0, extraflags = 0;
1949
+
1950
+ if (!NIL_P(gz->orig_name)) {
1951
+ flags |= GZ_FLAG_ORIG_NAME;
1952
+ }
1953
+ if (!NIL_P(gz->comment)) {
1954
+ flags |= GZ_FLAG_COMMENT;
1955
+ }
1956
+ if (gz->mtime == 0) {
1957
+ gz->mtime = time(0);
1958
+ }
1959
+
1960
+ if (gz->level == Z_BEST_SPEED) {
1961
+ extraflags |= GZ_EXTRAFLAG_FAST;
1962
+ }
1963
+ else if (gz->level == Z_BEST_COMPRESSION) {
1964
+ extraflags |= GZ_EXTRAFLAG_SLOW;
1965
+ }
1966
+
1967
+ buf[0] = GZ_MAGIC1;
1968
+ buf[1] = GZ_MAGIC2;
1969
+ buf[2] = GZ_METHOD_DEFLATE;
1970
+ buf[3] = flags;
1971
+ gzfile_set32(gz->mtime, &buf[4]);
1972
+ buf[8] = extraflags;
1973
+ buf[9] = gz->os_code;
1974
+ zstream_append_buffer(&gz->z, buf, sizeof(buf));
1975
+
1976
+ if (!NIL_P(gz->orig_name)) {
1977
+ zstream_append_buffer2(&gz->z, gz->orig_name);
1978
+ zstream_append_buffer(&gz->z, "\0", 1);
1979
+ }
1980
+ if (!NIL_P(gz->comment)) {
1981
+ zstream_append_buffer2(&gz->z, gz->comment);
1982
+ zstream_append_buffer(&gz->z, "\0", 1);
1983
+ }
1984
+
1985
+ gz->z.flags |= GZFILE_FLAG_HEADER_FINISHED;
1986
+ }
1987
+
1988
+ static void
1989
+ gzfile_make_footer(gz)
1990
+ struct gzfile *gz;
1991
+ {
1992
+ unsigned char buf[8]; /* 8 is the size of gzip footer */
1993
+
1994
+ gzfile_set32(gz->crc, buf);
1995
+ gzfile_set32(gz->z.stream.total_in, &buf[4]);
1996
+ zstream_append_buffer(&gz->z, buf, sizeof(buf));
1997
+ gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
1998
+ }
1999
+
2000
+ static void
2001
+ gzfile_read_header(gz)
2002
+ struct gzfile *gz;
2003
+ {
2004
+ const unsigned char *head;
2005
+ long len;
2006
+ char flags, *p;
2007
+
2008
+ if (!gzfile_read_raw_ensure(gz, 10)) { /* 10 is the size of gzip header */
2009
+ rb_raise(cGzError, "not in gzip format");
2010
+ }
2011
+
2012
+ head = RSTRING(gz->z.input)->ptr;
2013
+
2014
+ if (head[0] != GZ_MAGIC1 || head[1] != GZ_MAGIC2) {
2015
+ rb_raise(cGzError, "not in gzip format");
2016
+ }
2017
+ if (head[2] != GZ_METHOD_DEFLATE) {
2018
+ rb_raise(cGzError, "unsupported compression method %d", head[2]);
2019
+ }
2020
+
2021
+ flags = head[3];
2022
+ if (flags & GZ_FLAG_MULTIPART) {
2023
+ rb_raise(cGzError, "multi-part gzip file is not supported");
2024
+ }
2025
+ else if (flags & GZ_FLAG_ENCRYPT) {
2026
+ rb_raise(cGzError, "encrypted gzip file is not supported");
2027
+ }
2028
+ else if (flags & GZ_FLAG_UNKNOWN_MASK) {
2029
+ rb_raise(cGzError, "unknown flags 0x%02x", flags);
2030
+ }
2031
+
2032
+ if (head[8] & GZ_EXTRAFLAG_FAST) {
2033
+ gz->level = Z_BEST_SPEED;
2034
+ }
2035
+ else if (head[8] & GZ_EXTRAFLAG_SLOW) {
2036
+ gz->level = Z_BEST_COMPRESSION;
2037
+ }
2038
+ else {
2039
+ gz->level = Z_DEFAULT_COMPRESSION;
2040
+ }
2041
+
2042
+ gz->mtime = gzfile_get32(&head[4]);
2043
+ gz->os_code = head[9];
2044
+ zstream_discard_input(&gz->z, 10);
2045
+
2046
+ if (flags & GZ_FLAG_EXTRA) {
2047
+ if (!gzfile_read_raw_ensure(gz, 2)) {
2048
+ rb_raise(cGzError, "unexpected end of file");
2049
+ }
2050
+ len = gzfile_get16(RSTRING(gz->z.input)->ptr);
2051
+ if (!gzfile_read_raw_ensure(gz, 2 + len)) {
2052
+ rb_raise(cGzError, "unexpected end of file");
2053
+ }
2054
+ zstream_discard_input(&gz->z, 2 + len);
2055
+ }
2056
+ if (flags & GZ_FLAG_ORIG_NAME) {
2057
+ p = gzfile_read_raw_until_zero(gz, 0);
2058
+ len = p - RSTRING(gz->z.input)->ptr;
2059
+ gz->orig_name = rb_str_new(RSTRING(gz->z.input)->ptr, len);
2060
+ OBJ_TAINT(gz->orig_name); /* for safe */
2061
+ zstream_discard_input(&gz->z, len + 1);
2062
+ }
2063
+ if (flags & GZ_FLAG_COMMENT) {
2064
+ p = gzfile_read_raw_until_zero(gz, 0);
2065
+ len = p - RSTRING(gz->z.input)->ptr;
2066
+ gz->comment = rb_str_new(RSTRING(gz->z.input)->ptr, len);
2067
+ OBJ_TAINT(gz->comment); /* for safe */
2068
+ zstream_discard_input(&gz->z, len + 1);
2069
+ }
2070
+
2071
+ if (gz->z.input != Qnil && RSTRING(gz->z.input)->len > 0) {
2072
+ zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH);
2073
+ }
2074
+ }
2075
+
2076
+ static void
2077
+ gzfile_check_footer(gz)
2078
+ struct gzfile *gz;
2079
+ {
2080
+ unsigned long crc, length;
2081
+
2082
+ gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
2083
+
2084
+ if (!gzfile_read_raw_ensure(gz, 8)) { /* 8 is the size of gzip footer */
2085
+ rb_raise(cNoFooter, "footer is not found");
2086
+ }
2087
+
2088
+ crc = gzfile_get32(RSTRING(gz->z.input)->ptr);
2089
+ length = gzfile_get32(RSTRING(gz->z.input)->ptr + 4);
2090
+
2091
+ gz->z.stream.total_in += 8; /* to rewind correctly */
2092
+ zstream_discard_input(&gz->z, 8);
2093
+
2094
+ if (gz->crc != crc) {
2095
+ rb_raise(cCRCError, "invalid compressed data -- crc error");
2096
+ }
2097
+ if ((gz->z.stream.total_out & 0xFFFFFFFFUL) != length) {
2098
+ rb_raise(cLengthError, "invalid compressed data -- length error");
2099
+ }
2100
+ }
2101
+
2102
+ static void
2103
+ gzfile_write(gz, str, len)
2104
+ struct gzfile *gz;
2105
+ Bytef *str;
2106
+ uInt len;
2107
+ {
2108
+ if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2109
+ gzfile_make_header(gz);
2110
+ }
2111
+
2112
+ if (len > 0 || (gz->z.flags & GZFILE_FLAG_SYNC)) {
2113
+ gz->crc = crc32(gz->crc, str, len);
2114
+ zstream_run(&gz->z, str, len, (gz->z.flags & GZFILE_FLAG_SYNC)
2115
+ ? Z_SYNC_FLUSH : Z_NO_FLUSH);
2116
+ }
2117
+ gzfile_write_raw(gz);
2118
+ }
2119
+
2120
+ static long
2121
+ gzfile_read_more(gz)
2122
+ struct gzfile *gz;
2123
+ {
2124
+ volatile VALUE str;
2125
+
2126
+ while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2127
+ str = gzfile_read_raw(gz);
2128
+ if (NIL_P(str)) {
2129
+ if (!ZSTREAM_IS_FINISHED(&gz->z)) {
2130
+ rb_raise(cGzError, "unexpected end of file");
2131
+ }
2132
+ break;
2133
+ }
2134
+ if (RSTRING(str)->len > 0) { /* prevent Z_BUF_ERROR */
2135
+ zstream_run(&gz->z, RSTRING(str)->ptr, RSTRING(str)->len,
2136
+ Z_SYNC_FLUSH);
2137
+ }
2138
+ if (gz->z.buf_filled > 0) break;
2139
+ }
2140
+ return gz->z.buf_filled;
2141
+ }
2142
+
2143
+ static void
2144
+ gzfile_calc_crc(gz, str)
2145
+ struct gzfile *gz;
2146
+ VALUE str;
2147
+ {
2148
+ if (RSTRING(str)->len <= gz->ungetc) {
2149
+ gz->ungetc -= RSTRING(str)->len;
2150
+ }
2151
+ else {
2152
+ gz->crc = crc32(gz->crc, RSTRING(str)->ptr + gz->ungetc,
2153
+ RSTRING(str)->len - gz->ungetc);
2154
+ gz->ungetc = 0;
2155
+ }
2156
+ }
2157
+
2158
+ static VALUE
2159
+ gzfile_read(gz, len)
2160
+ struct gzfile *gz;
2161
+ int len;
2162
+ {
2163
+ VALUE dst;
2164
+
2165
+ if (len < 0)
2166
+ rb_raise(rb_eArgError, "negative length %d given", len);
2167
+ if (len == 0)
2168
+ return rb_str_new(0, 0);
2169
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
2170
+ gzfile_read_more(gz);
2171
+ }
2172
+ if (GZFILE_IS_FINISHED(gz)) {
2173
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2174
+ gzfile_check_footer(gz);
2175
+ }
2176
+ return Qnil;
2177
+ }
2178
+
2179
+ dst = zstream_shift_buffer(&gz->z, len);
2180
+ gzfile_calc_crc(gz, dst);
2181
+
2182
+ OBJ_TAINT(dst); /* for safe */
2183
+ return dst;
2184
+ }
2185
+
2186
+ static VALUE
2187
+ gzfile_read_all(gz)
2188
+ struct gzfile *gz;
2189
+ {
2190
+ VALUE dst;
2191
+
2192
+ while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2193
+ gzfile_read_more(gz);
2194
+ }
2195
+ if (GZFILE_IS_FINISHED(gz)) {
2196
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2197
+ gzfile_check_footer(gz);
2198
+ }
2199
+ return rb_str_new(0, 0);
2200
+ }
2201
+
2202
+ dst = zstream_detach_buffer(&gz->z);
2203
+ gzfile_calc_crc(gz, dst);
2204
+
2205
+ OBJ_TAINT(dst); /* for safe */
2206
+ return dst;
2207
+ }
2208
+
2209
+ static void
2210
+ gzfile_ungetc(gz, c)
2211
+ struct gzfile *gz;
2212
+ int c;
2213
+ {
2214
+ zstream_buffer_ungetc(&gz->z, c);
2215
+ gz->ungetc++;
2216
+ }
2217
+
2218
+ static VALUE
2219
+ gzfile_writer_end_run(arg)
2220
+ VALUE arg;
2221
+ {
2222
+ struct gzfile *gz = (struct gzfile *)arg;
2223
+
2224
+ if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2225
+ gzfile_make_header(gz);
2226
+ }
2227
+
2228
+ zstream_run(&gz->z, "", 0, Z_FINISH);
2229
+ gzfile_make_footer(gz);
2230
+ gzfile_write_raw(gz);
2231
+
2232
+ return Qnil;
2233
+ }
2234
+
2235
+ static void
2236
+ gzfile_writer_end(gz)
2237
+ struct gzfile *gz;
2238
+ {
2239
+ if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2240
+ gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2241
+
2242
+ rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
2243
+ }
2244
+
2245
+ static VALUE
2246
+ gzfile_reader_end_run(arg)
2247
+ VALUE arg;
2248
+ {
2249
+ struct gzfile *gz = (struct gzfile *)arg;
2250
+
2251
+ if (GZFILE_IS_FINISHED(gz)
2252
+ && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2253
+ gzfile_check_footer(gz);
2254
+ }
2255
+
2256
+ return Qnil;
2257
+ }
2258
+
2259
+ static void
2260
+ gzfile_reader_end(gz)
2261
+ struct gzfile *gz;
2262
+ {
2263
+ if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2264
+ gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2265
+
2266
+ rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
2267
+ }
2268
+
2269
+ static void
2270
+ gzfile_reader_rewind(gz)
2271
+ struct gzfile *gz;
2272
+ {
2273
+ long n;
2274
+
2275
+ n = gz->z.stream.total_in;
2276
+ if (!NIL_P(gz->z.input)) {
2277
+ n += RSTRING(gz->z.input)->len;
2278
+ }
2279
+
2280
+ rb_funcall(gz->io, id_seek, 2, rb_int2inum(-n), INT2FIX(1));
2281
+ gzfile_reset(gz);
2282
+ }
2283
+
2284
+ static VALUE
2285
+ gzfile_reader_get_unused(gz)
2286
+ struct gzfile *gz;
2287
+ {
2288
+ VALUE str;
2289
+
2290
+ if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
2291
+ if (!GZFILE_IS_FINISHED(gz)) return Qnil;
2292
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2293
+ gzfile_check_footer(gz);
2294
+ }
2295
+ if (NIL_P(gz->z.input)) return Qnil;
2296
+
2297
+ str = rb_str_dup(gz->z.input);
2298
+ OBJ_TAINT(str); /* for safe */
2299
+ return str;
2300
+ }
2301
+
2302
+ static struct gzfile *
2303
+ get_gzfile(obj)
2304
+ VALUE obj;
2305
+ {
2306
+ struct gzfile *gz;
2307
+
2308
+ Data_Get_Struct(obj, struct gzfile, gz);
2309
+ if (!ZSTREAM_IS_READY(&gz->z)) {
2310
+ rb_raise(cGzError, "closed gzip stream");
2311
+ }
2312
+ return gz;
2313
+ }
2314
+
2315
+
2316
+ /* ------------------------------------------------------------------------- */
2317
+
2318
+ /*
2319
+ * Document-class: Zlib::GzipFile
2320
+ *
2321
+ * Zlib::GzipFile is an abstract class for handling a gzip formatted
2322
+ * compressed file. The operations are defined in the subclasses,
2323
+ * Zlib::GzipReader for reading, and Zlib::GzipWriter for writing.
2324
+ *
2325
+ * GzipReader should be used by associating an IO, or IO-like, object.
2326
+ */
2327
+
2328
+
2329
+ static VALUE
2330
+ gzfile_ensure_close(obj)
2331
+ VALUE obj;
2332
+ {
2333
+ struct gzfile *gz;
2334
+
2335
+ Data_Get_Struct(obj, struct gzfile, gz);
2336
+ if (ZSTREAM_IS_READY(&gz->z)) {
2337
+ gzfile_close(gz, 1);
2338
+ }
2339
+ return Qnil;
2340
+ }
2341
+
2342
+ /*
2343
+ * See Zlib::GzipReader#wrap and Zlib::GzipWriter#wrap.
2344
+ */
2345
+ static VALUE
2346
+ rb_gzfile_s_wrap(argc, argv, klass)
2347
+ int argc;
2348
+ VALUE *argv;
2349
+ VALUE klass;
2350
+ {
2351
+ VALUE obj = rb_class_new_instance(argc, argv, klass);
2352
+
2353
+ if (rb_block_given_p()) {
2354
+ return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
2355
+ }
2356
+ else {
2357
+ return obj;
2358
+ }
2359
+ }
2360
+
2361
+ /*
2362
+ * See Zlib::GzipReader#open and Zlib::GzipWriter#open.
2363
+ */
2364
+ static VALUE
2365
+ gzfile_s_open(argc, argv, klass, mode)
2366
+ int argc;
2367
+ VALUE *argv;
2368
+ VALUE klass;
2369
+ const char *mode;
2370
+ {
2371
+ VALUE io, filename;
2372
+
2373
+ if (argc < 1) {
2374
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
2375
+ }
2376
+ filename = argv[0];
2377
+ SafeStringValue(filename);
2378
+ io = rb_file_open(RSTRING(filename)->ptr, mode);
2379
+
2380
+ argv[0] = io;
2381
+ return rb_gzfile_s_wrap(argc, argv, klass);
2382
+ }
2383
+
2384
+ /*
2385
+ * Same as IO.
2386
+ */
2387
+ static VALUE
2388
+ rb_gzfile_to_io(obj)
2389
+ VALUE obj;
2390
+ {
2391
+ return get_gzfile(obj)->io;
2392
+ }
2393
+
2394
+ /*
2395
+ * Returns CRC value of the uncompressed data.
2396
+ */
2397
+ static VALUE
2398
+ rb_gzfile_crc(obj)
2399
+ VALUE obj;
2400
+ {
2401
+ return rb_uint2inum(get_gzfile(obj)->crc);
2402
+ }
2403
+
2404
+ /*
2405
+ * Returns last modification time recorded in the gzip file header.
2406
+ */
2407
+ static VALUE
2408
+ rb_gzfile_mtime(obj)
2409
+ VALUE obj;
2410
+ {
2411
+ return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
2412
+ }
2413
+
2414
+ /*
2415
+ * Returns compression level.
2416
+ */
2417
+ static VALUE
2418
+ rb_gzfile_level(obj)
2419
+ VALUE obj;
2420
+ {
2421
+ return INT2FIX(get_gzfile(obj)->level);
2422
+ }
2423
+
2424
+ /*
2425
+ * Returns OS code number recorded in the gzip file header.
2426
+ */
2427
+ static VALUE
2428
+ rb_gzfile_os_code(obj)
2429
+ VALUE obj;
2430
+ {
2431
+ return INT2FIX(get_gzfile(obj)->os_code);
2432
+ }
2433
+
2434
+ /*
2435
+ * Returns original filename recorded in the gzip file header, or +nil+ if
2436
+ * original filename is not present.
2437
+ */
2438
+ static VALUE
2439
+ rb_gzfile_orig_name(obj)
2440
+ VALUE obj;
2441
+ {
2442
+ VALUE str = get_gzfile(obj)->orig_name;
2443
+ if (!NIL_P(str)) {
2444
+ str = rb_str_dup(str);
2445
+ }
2446
+ OBJ_TAINT(str); /* for safe */
2447
+ return str;
2448
+ }
2449
+
2450
+ /*
2451
+ * Returns comments recorded in the gzip file header, or nil if the comments
2452
+ * is not present.
2453
+ */
2454
+ static VALUE
2455
+ rb_gzfile_comment(obj)
2456
+ VALUE obj;
2457
+ {
2458
+ VALUE str = get_gzfile(obj)->comment;
2459
+ if (!NIL_P(str)) {
2460
+ str = rb_str_dup(str);
2461
+ }
2462
+ OBJ_TAINT(str); /* for safe */
2463
+ return str;
2464
+ }
2465
+
2466
+ /*
2467
+ * ???
2468
+ */
2469
+ static VALUE
2470
+ rb_gzfile_lineno(obj)
2471
+ VALUE obj;
2472
+ {
2473
+ return INT2NUM(get_gzfile(obj)->lineno);
2474
+ }
2475
+
2476
+ /*
2477
+ * ???
2478
+ */
2479
+ static VALUE
2480
+ rb_gzfile_set_lineno(obj, lineno)
2481
+ VALUE obj, lineno;
2482
+ {
2483
+ struct gzfile *gz = get_gzfile(obj);
2484
+ gz->lineno = NUM2INT(lineno);
2485
+ return lineno;
2486
+ }
2487
+
2488
+ /*
2489
+ * ???
2490
+ */
2491
+ static VALUE
2492
+ rb_gzfile_set_mtime(obj, mtime)
2493
+ VALUE obj, mtime;
2494
+ {
2495
+ struct gzfile *gz = get_gzfile(obj);
2496
+ VALUE val;
2497
+
2498
+ if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
2499
+ rb_raise(cGzError, "header is already written");
2500
+ }
2501
+
2502
+ if (FIXNUM_P(mtime)) {
2503
+ gz->mtime = FIX2INT(mtime);
2504
+ }
2505
+ else {
2506
+ val = rb_Integer(mtime);
2507
+ gz->mtime = FIXNUM_P(val) ? FIX2INT(val) : rb_big2ulong(val);
2508
+ }
2509
+ return mtime;
2510
+ }
2511
+
2512
+ /*
2513
+ * ???
2514
+ */
2515
+ static VALUE
2516
+ rb_gzfile_set_orig_name(obj, str)
2517
+ VALUE obj, str;
2518
+ {
2519
+ struct gzfile *gz = get_gzfile(obj);
2520
+ VALUE s;
2521
+ char *p;
2522
+
2523
+ if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
2524
+ rb_raise(cGzError, "header is already written");
2525
+ }
2526
+ s = rb_str_dup(rb_str_to_str(str));
2527
+ p = memchr(RSTRING(s)->ptr, '\0', RSTRING(s)->len);
2528
+ if (p) {
2529
+ rb_str_resize(s, p - RSTRING(s)->ptr);
2530
+ }
2531
+ gz->orig_name = s;
2532
+ return str;
2533
+ }
2534
+
2535
+ /*
2536
+ * ???
2537
+ */
2538
+ static VALUE
2539
+ rb_gzfile_set_comment(obj, str)
2540
+ VALUE obj, str;
2541
+ {
2542
+ struct gzfile *gz = get_gzfile(obj);
2543
+ VALUE s;
2544
+ char *p;
2545
+
2546
+ if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
2547
+ rb_raise(cGzError, "header is already written");
2548
+ }
2549
+ s = rb_str_dup(rb_str_to_str(str));
2550
+ p = memchr(RSTRING(s)->ptr, '\0', RSTRING(s)->len);
2551
+ if (p) {
2552
+ rb_str_resize(s, p - RSTRING(s)->ptr);
2553
+ }
2554
+ gz->comment = s;
2555
+ return str;
2556
+ }
2557
+
2558
+ /*
2559
+ * Closes the GzipFile object. This method calls close method of the
2560
+ * associated IO object. Returns the associated IO object.
2561
+ */
2562
+ static VALUE
2563
+ rb_gzfile_close(obj)
2564
+ VALUE obj;
2565
+ {
2566
+ struct gzfile *gz = get_gzfile(obj);
2567
+ VALUE io;
2568
+
2569
+ io = gz->io;
2570
+ gzfile_close(gz, 1);
2571
+ return io;
2572
+ }
2573
+
2574
+ /*
2575
+ * Closes the GzipFile object. Unlike Zlib::GzipFile#close, this method never
2576
+ * calls the close method of the associated IO object. Returns the associated IO
2577
+ * object.
2578
+ */
2579
+ static VALUE
2580
+ rb_gzfile_finish(obj)
2581
+ VALUE obj;
2582
+ {
2583
+ struct gzfile *gz = get_gzfile(obj);
2584
+ VALUE io;
2585
+
2586
+ io = gz->io;
2587
+ gzfile_close(gz, 0);
2588
+ return io;
2589
+ }
2590
+
2591
+ /*
2592
+ * Same as IO.
2593
+ */
2594
+ static VALUE
2595
+ rb_gzfile_closed_p(obj)
2596
+ VALUE obj;
2597
+ {
2598
+ struct gzfile *gz;
2599
+ Data_Get_Struct(obj, struct gzfile, gz);
2600
+ return NIL_P(gz->io) ? Qtrue : Qfalse;
2601
+ }
2602
+
2603
+ /*
2604
+ * ???
2605
+ */
2606
+ static VALUE
2607
+ rb_gzfile_eof_p(obj)
2608
+ VALUE obj;
2609
+ {
2610
+ struct gzfile *gz = get_gzfile(obj);
2611
+ return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
2612
+ }
2613
+
2614
+ /*
2615
+ * Same as IO.
2616
+ */
2617
+ static VALUE
2618
+ rb_gzfile_sync(obj)
2619
+ VALUE obj;
2620
+ {
2621
+ return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
2622
+ }
2623
+
2624
+ /*
2625
+ * call-seq: sync = flag
2626
+ *
2627
+ * Same as IO. If flag is +true+, the associated IO object must respond to the
2628
+ * +flush+ method. While +sync+ mode is +true+, the compression ratio
2629
+ * decreases sharply.
2630
+ */
2631
+ static VALUE
2632
+ rb_gzfile_set_sync(obj, mode)
2633
+ VALUE obj, mode;
2634
+ {
2635
+ struct gzfile *gz = get_gzfile(obj);
2636
+
2637
+ if (RTEST(mode)) {
2638
+ gz->z.flags |= GZFILE_FLAG_SYNC;
2639
+ }
2640
+ else {
2641
+ gz->z.flags &= ~GZFILE_FLAG_SYNC;
2642
+ }
2643
+ return mode;
2644
+ }
2645
+
2646
+ /*
2647
+ * ???
2648
+ */
2649
+ static VALUE
2650
+ rb_gzfile_total_in(obj)
2651
+ VALUE obj;
2652
+ {
2653
+ return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
2654
+ }
2655
+
2656
+ /*
2657
+ * ???
2658
+ */
2659
+ static VALUE
2660
+ rb_gzfile_total_out(obj)
2661
+ VALUE obj;
2662
+ {
2663
+ struct gzfile *gz = get_gzfile(obj);
2664
+ return rb_uint2inum(gz->z.stream.total_out - gz->z.buf_filled);
2665
+ }
2666
+
2667
+
2668
+ /* ------------------------------------------------------------------------- */
2669
+
2670
+ /*
2671
+ * Document-class: Zlib::GzipWriter
2672
+ *
2673
+ * Zlib::GzipWriter is a class for writing gzipped files. GzipWriter should
2674
+ * be used with an instance of IO, or IO-like, object.
2675
+ *
2676
+ * For example:
2677
+ *
2678
+ * Zlib::GzipWriter.open('hoge.gz') do |gz|
2679
+ * gz.write 'jugemu jugemu gokou no surikire...'
2680
+ * end
2681
+ *
2682
+ * File.open('hoge.gz', 'w') do |f|
2683
+ * gz = Zlib::GzipWriter.new(f)
2684
+ * gz.write 'jugemu jugemu gokou no surikire...'
2685
+ * gz.close
2686
+ * end
2687
+ *
2688
+ * # TODO: test these. Are they equivalent? Can GzipWriter.new take a
2689
+ * # block?
2690
+ *
2691
+ * NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close
2692
+ * GzipWriter objects by Zlib::GzipWriter#close etc. Otherwise, GzipWriter
2693
+ * will be not able to write the gzip footer and will generate a broken gzip
2694
+ * file.
2695
+ */
2696
+
2697
+ static VALUE
2698
+ rb_gzwriter_s_allocate(klass)
2699
+ VALUE klass;
2700
+ {
2701
+ return gzfile_writer_new(klass);
2702
+ }
2703
+
2704
+ /*
2705
+ * call-seq: Zlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... }
2706
+ *
2707
+ * Opens a file specified by +filename+ for writing gzip compressed data, and
2708
+ * returns a GzipWriter object associated with that file. Further details of
2709
+ * this method are found in Zlib::GzipWriter.new and Zlib::GzipWriter#wrap.
2710
+ */
2711
+ static VALUE
2712
+ rb_gzwriter_s_open(argc, argv, klass)
2713
+ int argc;
2714
+ VALUE *argv;
2715
+ VALUE klass;
2716
+ {
2717
+ return gzfile_s_open(argc, argv, klass, "wb");
2718
+ }
2719
+
2720
+ /*
2721
+ * call-seq: Zlib::GzipWriter.new(io, level, strategy)
2722
+ *
2723
+ * Creates a GzipWriter object associated with +io+. +level+ and +strategy+
2724
+ * should be the same as the arguments of Zlib::Deflate.new. The GzipWriter
2725
+ * object writes gzipped data to +io+. At least, +io+ must respond to the
2726
+ * +write+ method that behaves same as write method in IO class.
2727
+ */
2728
+ static VALUE
2729
+ rb_gzwriter_initialize(argc, argv, obj)
2730
+ int argc;
2731
+ VALUE *argv;
2732
+ VALUE obj;
2733
+ {
2734
+ struct gzfile *gz;
2735
+ VALUE io, level, strategy;
2736
+ int err;
2737
+
2738
+ rb_scan_args(argc, argv, "12", &io, &level, &strategy);
2739
+ Data_Get_Struct(obj, struct gzfile, gz);
2740
+
2741
+ /* this is undocumented feature of zlib */
2742
+ gz->level = ARG_LEVEL(level);
2743
+ err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
2744
+ -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
2745
+ if (err != Z_OK) {
2746
+ raise_zlib_error(err, gz->z.stream.msg);
2747
+ }
2748
+ gz->io = io;
2749
+ ZSTREAM_READY(&gz->z);
2750
+
2751
+ return obj;
2752
+ }
2753
+
2754
+ /*
2755
+ * call-seq: flush(flush=nil)
2756
+ *
2757
+ * Flushes all the internal buffers of the GzipWriter object. The meaning of
2758
+ * +flush+ is same as in Zlib::Deflate#deflate. <tt>Zlib::SYNC_FLUSH</tt> is used if
2759
+ * +flush+ is omitted. It is no use giving flush <tt>Zlib::NO_FLUSH</tt>.
2760
+ */
2761
+ static VALUE
2762
+ rb_gzwriter_flush(argc, argv, obj)
2763
+ int argc;
2764
+ VALUE *argv;
2765
+ VALUE obj;
2766
+ {
2767
+ struct gzfile *gz = get_gzfile(obj);
2768
+ VALUE v_flush;
2769
+ int flush;
2770
+
2771
+ rb_scan_args(argc, argv, "01", &v_flush);
2772
+
2773
+ flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
2774
+ if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
2775
+ zstream_run(&gz->z, "", 0, flush);
2776
+ }
2777
+
2778
+ gzfile_write_raw(gz);
2779
+ if (rb_respond_to(gz->io, id_flush)) {
2780
+ rb_funcall(gz->io, id_flush, 0);
2781
+ }
2782
+ return obj;
2783
+ }
2784
+
2785
+ /*
2786
+ * Same as IO.
2787
+ */
2788
+ static VALUE
2789
+ rb_gzwriter_write(obj, str)
2790
+ VALUE obj, str;
2791
+ {
2792
+ struct gzfile *gz = get_gzfile(obj);
2793
+
2794
+ if (TYPE(str) != T_STRING) {
2795
+ str = rb_obj_as_string(str);
2796
+ }
2797
+ gzfile_write(gz, RSTRING(str)->ptr, RSTRING(str)->len);
2798
+ return INT2FIX(RSTRING(str)->len);
2799
+ }
2800
+
2801
+ /*
2802
+ * Same as IO.
2803
+ */
2804
+ static VALUE
2805
+ rb_gzwriter_putc(obj, ch)
2806
+ VALUE obj, ch;
2807
+ {
2808
+ struct gzfile *gz = get_gzfile(obj);
2809
+ char c = NUM2CHR(ch);
2810
+
2811
+ gzfile_write(gz, &c, 1);
2812
+ return ch;
2813
+ }
2814
+
2815
+
2816
+
2817
+ /*
2818
+ * Document-method: <<
2819
+ * Same as IO.
2820
+ */
2821
+ #define rb_gzwriter_addstr rb_io_addstr
2822
+ /*
2823
+ * Document-method: printf
2824
+ * Same as IO.
2825
+ */
2826
+ #define rb_gzwriter_printf rb_io_printf
2827
+ /*
2828
+ * Document-method: print
2829
+ * Same as IO.
2830
+ */
2831
+ #define rb_gzwriter_print rb_io_print
2832
+ /*
2833
+ * Document-method: puts
2834
+ * Same as IO.
2835
+ */
2836
+ #define rb_gzwriter_puts rb_io_puts
2837
+
2838
+
2839
+ /* ------------------------------------------------------------------------- */
2840
+
2841
+ /*
2842
+ * Document-class: Zlib::GzipReader
2843
+ *
2844
+ * Zlib::GzipReader is the class for reading a gzipped file. GzipReader should
2845
+ * be used an IO, or -IO-lie, object.
2846
+ *
2847
+ * Zlib::GzipReader.open('hoge.gz') {|gz|
2848
+ * print gz.read
2849
+ * }
2850
+ *
2851
+ * File.open('hoge.gz') do |f|
2852
+ * gz = Zlib::GzipReader.new(f)
2853
+ * print gz.read
2854
+ * gz.close
2855
+ * end
2856
+ *
2857
+ * # TODO: test these. Are they equivalent? Can GzipReader.new take a
2858
+ * # block?
2859
+ *
2860
+ * == Method Catalogue
2861
+ *
2862
+ * The following methods in Zlib::GzipReader are just like their counterparts
2863
+ * in IO, but they raise Zlib::Error or Zlib::GzipFile::Error exception if an
2864
+ * error was found in the gzip file.
2865
+ * - #each
2866
+ * - #each_line
2867
+ * - #each_byte
2868
+ * - #gets
2869
+ * - #getc
2870
+ * - #lineno
2871
+ * - #lineno=
2872
+ * - #read
2873
+ * - #readchar
2874
+ * - #readline
2875
+ * - #readlines
2876
+ * - #ungetc
2877
+ *
2878
+ * Be careful of the footer of the gzip file. A gzip file has the checksum of
2879
+ * pre-compressed data in its footer. GzipReader checks all uncompressed data
2880
+ * against that checksum at the following cases, and if it fails, raises
2881
+ * <tt>Zlib::GzipFile::NoFooter</tt>, <tt>Zlib::GzipFile::CRCError</tt>, or
2882
+ * <tt>Zlib::GzipFile::LengthError</tt> exception.
2883
+ *
2884
+ * - When an reading request is received beyond the end of file (the end of
2885
+ * compressed data). That is, when Zlib::GzipReader#read,
2886
+ * Zlib::GzipReader#gets, or some other methods for reading returns nil.
2887
+ * - When Zlib::GzipFile#close method is called after the object reaches the
2888
+ * end of file.
2889
+ * - When Zlib::GzipReader#unused method is called after the object reaches
2890
+ * the end of file.
2891
+ *
2892
+ * The rest of the methods are adequately described in their own
2893
+ * documentation.
2894
+ */
2895
+
2896
+ static VALUE
2897
+ rb_gzreader_s_allocate(klass)
2898
+ VALUE klass;
2899
+ {
2900
+ return gzfile_reader_new(klass);
2901
+ }
2902
+
2903
+ /*
2904
+ * call-seq: Zlib::GzipReader.open(filename) {|gz| ... }
2905
+ *
2906
+ * Opens a file specified by +filename+ as a gzipped file, and returns a
2907
+ * GzipReader object associated with that file. Further details of this method
2908
+ * are in Zlib::GzipReader.new and ZLib::GzipReader.wrap.
2909
+ */
2910
+ static VALUE
2911
+ rb_gzreader_s_open(argc, argv, klass)
2912
+ int argc;
2913
+ VALUE *argv;
2914
+ VALUE klass;
2915
+ {
2916
+ return gzfile_s_open(argc, argv, klass, "rb");
2917
+ }
2918
+
2919
+ /*
2920
+ * call-seq: Zlib::GzipReader.new(io)
2921
+ *
2922
+ * Creates a GzipReader object associated with +io+. The GzipReader object reads
2923
+ * gzipped data from +io+, and parses/decompresses them. At least, +io+ must have
2924
+ * a +read+ method that behaves same as the +read+ method in IO class.
2925
+ *
2926
+ * If the gzip file header is incorrect, raises an Zlib::GzipFile::Error
2927
+ * exception.
2928
+ */
2929
+ static VALUE
2930
+ rb_gzreader_initialize(obj, io)
2931
+ VALUE obj, io;
2932
+ {
2933
+ struct gzfile *gz;
2934
+ int err;
2935
+
2936
+ Data_Get_Struct(obj, struct gzfile, gz);
2937
+
2938
+ /* this is undocumented feature of zlib */
2939
+ err = inflateInit2(&gz->z.stream, -MAX_WBITS);
2940
+ if (err != Z_OK) {
2941
+ raise_zlib_error(err, gz->z.stream.msg);
2942
+ }
2943
+ gz->io = io;
2944
+ ZSTREAM_READY(&gz->z);
2945
+ gzfile_read_header(gz);
2946
+
2947
+ return obj;
2948
+ }
2949
+
2950
+ /*
2951
+ * Resets the position of the file pointer to the point created the GzipReader
2952
+ * object. The associated IO object needs to respond to the +seek+ method.
2953
+ */
2954
+ static VALUE
2955
+ rb_gzreader_rewind(obj)
2956
+ VALUE obj;
2957
+ {
2958
+ struct gzfile *gz = get_gzfile(obj);
2959
+ gzfile_reader_rewind(gz);
2960
+ return INT2FIX(0);
2961
+ }
2962
+
2963
+ /*
2964
+ * Returns the rest of the data which had read for parsing gzip format, or
2965
+ * +nil+ if the whole gzip file is not parsed yet.
2966
+ */
2967
+ static VALUE
2968
+ rb_gzreader_unused(obj)
2969
+ VALUE obj;
2970
+ {
2971
+ struct gzfile *gz;
2972
+ Data_Get_Struct(obj, struct gzfile, gz);
2973
+ return gzfile_reader_get_unused(gz);
2974
+ }
2975
+
2976
+ /*
2977
+ * See Zlib::GzipReader documentation for a description.
2978
+ */
2979
+ static VALUE
2980
+ rb_gzreader_read(argc, argv, obj)
2981
+ int argc;
2982
+ VALUE *argv;
2983
+ VALUE obj;
2984
+ {
2985
+ struct gzfile *gz = get_gzfile(obj);
2986
+ VALUE vlen;
2987
+ int len;
2988
+
2989
+ rb_scan_args(argc, argv, "01", &vlen);
2990
+ if (NIL_P(vlen)) {
2991
+ return gzfile_read_all(gz);
2992
+ }
2993
+
2994
+ len = NUM2INT(vlen);
2995
+ if (len < 0) {
2996
+ rb_raise(rb_eArgError, "negative length %d given", len);
2997
+ }
2998
+ return gzfile_read(gz, len);
2999
+ }
3000
+
3001
+ /*
3002
+ * See Zlib::GzipReader documentation for a description.
3003
+ */
3004
+ static VALUE
3005
+ rb_gzreader_getc(obj)
3006
+ VALUE obj;
3007
+ {
3008
+ struct gzfile *gz = get_gzfile(obj);
3009
+ VALUE dst;
3010
+
3011
+ dst = gzfile_read(gz, 1);
3012
+ if (!NIL_P(dst)) {
3013
+ dst = INT2FIX((unsigned int)(RSTRING(dst)->ptr[0]) & 0xff);
3014
+ }
3015
+ return dst;
3016
+ }
3017
+
3018
+ /*
3019
+ * See Zlib::GzipReader documentation for a description.
3020
+ */
3021
+ static VALUE
3022
+ rb_gzreader_readchar(obj)
3023
+ VALUE obj;
3024
+ {
3025
+ VALUE dst;
3026
+ dst = rb_gzreader_getc(obj);
3027
+ if (NIL_P(dst)) {
3028
+ rb_raise(rb_eEOFError, "end of file reached");
3029
+ }
3030
+ return dst;
3031
+ }
3032
+
3033
+ /*
3034
+ * See Zlib::GzipReader documentation for a description.
3035
+ */
3036
+ static VALUE
3037
+ rb_gzreader_each_byte(obj)
3038
+ VALUE obj;
3039
+ {
3040
+ VALUE c;
3041
+ while (!NIL_P(c = rb_gzreader_getc(obj))) {
3042
+ rb_yield(c);
3043
+ }
3044
+ return Qnil;
3045
+ }
3046
+
3047
+ /*
3048
+ * See Zlib::GzipReader documentation for a description.
3049
+ */
3050
+ static VALUE
3051
+ rb_gzreader_ungetc(obj, ch)
3052
+ VALUE obj, ch;
3053
+ {
3054
+ struct gzfile *gz = get_gzfile(obj);
3055
+ gzfile_ungetc(gz, NUM2CHR(ch));
3056
+ return Qnil;
3057
+ }
3058
+
3059
+ static void
3060
+ gzreader_skip_linebreaks(gz)
3061
+ struct gzfile *gz;
3062
+ {
3063
+ VALUE str;
3064
+ char *p;
3065
+ int n;
3066
+
3067
+ while (gz->z.buf_filled == 0) {
3068
+ if (GZFILE_IS_FINISHED(gz)) return;
3069
+ gzfile_read_more(gz);
3070
+ }
3071
+ n = 0;
3072
+ p = RSTRING(gz->z.buf)->ptr;
3073
+
3074
+ while (n++, *(p++) == '\n') {
3075
+ if (n >= gz->z.buf_filled) {
3076
+ str = zstream_detach_buffer(&gz->z);
3077
+ gzfile_calc_crc(gz, str);
3078
+ while (gz->z.buf_filled == 0) {
3079
+ if (GZFILE_IS_FINISHED(gz)) return;
3080
+ gzfile_read_more(gz);
3081
+ }
3082
+ n = 0;
3083
+ p = RSTRING(gz->z.buf)->ptr;
3084
+ }
3085
+ }
3086
+
3087
+ str = zstream_shift_buffer(&gz->z, n - 1);
3088
+ gzfile_calc_crc(gz, str);
3089
+ }
3090
+
3091
+ static void
3092
+ rscheck(rsptr, rslen, rs)
3093
+ char *rsptr;
3094
+ long rslen;
3095
+ VALUE rs;
3096
+ {
3097
+ if (RSTRING(rs)->ptr != rsptr && RSTRING(rs)->len != rslen)
3098
+ rb_raise(rb_eRuntimeError, "rs modified");
3099
+ }
3100
+
3101
+ static VALUE
3102
+ gzreader_gets(argc, argv, obj)
3103
+ int argc;
3104
+ VALUE *argv;
3105
+ VALUE obj;
3106
+ {
3107
+ struct gzfile *gz = get_gzfile(obj);
3108
+ volatile VALUE rs;
3109
+ VALUE dst;
3110
+ char *rsptr, *p, *res;
3111
+ long rslen, n;
3112
+ int rspara;
3113
+
3114
+ if (argc == 0) {
3115
+ rs = rb_rs;
3116
+ }
3117
+ else {
3118
+ rb_scan_args(argc, argv, "1", &rs);
3119
+ if (!NIL_P(rs)) {
3120
+ Check_Type(rs, T_STRING);
3121
+ }
3122
+ }
3123
+
3124
+ if (NIL_P(rs)) {
3125
+ dst = gzfile_read_all(gz);
3126
+ if (RSTRING(dst)->len != 0) gz->lineno++;
3127
+ else
3128
+ return Qnil;
3129
+ return dst;
3130
+ }
3131
+
3132
+ if (RSTRING(rs)->len == 0) {
3133
+ rsptr = "\n\n";
3134
+ rslen = 2;
3135
+ rspara = 1;
3136
+ } else {
3137
+ rsptr = RSTRING(rs)->ptr;
3138
+ rslen = RSTRING(rs)->len;
3139
+ rspara = 0;
3140
+ }
3141
+
3142
+ if (rspara) {
3143
+ gzreader_skip_linebreaks(gz);
3144
+ }
3145
+
3146
+ while (gz->z.buf_filled < rslen) {
3147
+ if (ZSTREAM_IS_FINISHED(&gz->z)) {
3148
+ if (gz->z.buf_filled > 0) gz->lineno++;
3149
+ return gzfile_read(gz, rslen);
3150
+ }
3151
+ gzfile_read_more(gz);
3152
+ }
3153
+
3154
+ p = RSTRING(gz->z.buf)->ptr;
3155
+ n = rslen;
3156
+ for (;;) {
3157
+ if (n > gz->z.buf_filled) {
3158
+ if (ZSTREAM_IS_FINISHED(&gz->z)) break;
3159
+ gzfile_read_more(gz);
3160
+ p = RSTRING(gz->z.buf)->ptr + n - rslen;
3161
+ }
3162
+ if (!rspara) rscheck(rsptr, rslen, rs);
3163
+ res = memchr(p, rsptr[0], (gz->z.buf_filled - n + 1));
3164
+ if (!res) {
3165
+ n = gz->z.buf_filled + 1;
3166
+ } else {
3167
+ n += (long)(res - p);
3168
+ p = res;
3169
+ if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
3170
+ p++, n++;
3171
+ }
3172
+ }
3173
+
3174
+ gz->lineno++;
3175
+ dst = gzfile_read(gz, n);
3176
+ if (rspara) {
3177
+ gzreader_skip_linebreaks(gz);
3178
+ }
3179
+
3180
+ return dst;
3181
+ }
3182
+
3183
+ /*
3184
+ * See Zlib::GzipReader documentation for a description.
3185
+ */
3186
+ static VALUE
3187
+ rb_gzreader_gets(argc, argv, obj)
3188
+ int argc;
3189
+ VALUE *argv;
3190
+ VALUE obj;
3191
+ {
3192
+ VALUE dst;
3193
+ dst = gzreader_gets(argc, argv, obj);
3194
+ if (!NIL_P(dst)) {
3195
+ rb_lastline_set(dst);
3196
+ }
3197
+ return dst;
3198
+ }
3199
+
3200
+ /*
3201
+ * See Zlib::GzipReader documentation for a description.
3202
+ */
3203
+ static VALUE
3204
+ rb_gzreader_readline(argc, argv, obj)
3205
+ int argc;
3206
+ VALUE *argv;
3207
+ VALUE obj;
3208
+ {
3209
+ VALUE dst;
3210
+ dst = rb_gzreader_gets(argc, argv, obj);
3211
+ if (NIL_P(dst)) {
3212
+ rb_raise(rb_eEOFError, "end of file reached");
3213
+ }
3214
+ return dst;
3215
+ }
3216
+
3217
+ /*
3218
+ * See Zlib::GzipReader documentation for a description.
3219
+ */
3220
+ static VALUE
3221
+ rb_gzreader_each(argc, argv, obj)
3222
+ int argc;
3223
+ VALUE *argv;
3224
+ VALUE obj;
3225
+ {
3226
+ VALUE str;
3227
+ while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
3228
+ rb_yield(str);
3229
+ }
3230
+ return obj;
3231
+ }
3232
+
3233
+ /*
3234
+ * See Zlib::GzipReader documentation for a description.
3235
+ */
3236
+ static VALUE
3237
+ rb_gzreader_readlines(argc, argv, obj)
3238
+ int argc;
3239
+ VALUE *argv;
3240
+ VALUE obj;
3241
+ {
3242
+ VALUE str, dst;
3243
+ dst = rb_ary_new();
3244
+ while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
3245
+ rb_ary_push(dst, str);
3246
+ }
3247
+ return dst;
3248
+ }
3249
+
3250
+ #endif /* GZIP_SUPPORT */
3251
+
3252
+
3253
+
3254
+ /*
3255
+ * The Zlib module contains several classes for compressing and decompressing
3256
+ * streams, and for working with "gzip" files.
3257
+ *
3258
+ * == Classes
3259
+ *
3260
+ * Following are the classes that are most likely to be of interest to the
3261
+ * user:
3262
+ * Zlib::Inflate
3263
+ * Zlib::Deflate
3264
+ * Zlib::GzipReader
3265
+ * Zlib::GzipWriter
3266
+ *
3267
+ * There are two important base classes for the classes above: Zlib::ZStream
3268
+ * and Zlib::GzipFile. Everything else is an error class.
3269
+ *
3270
+ * == Constants
3271
+ *
3272
+ * Here's a list.
3273
+ *
3274
+ * Zlib::VERSION
3275
+ * The Ruby/zlib version string.
3276
+ *
3277
+ * Zlib::ZLIB_VERSION
3278
+ * The string which represents the version of zlib.h.
3279
+ *
3280
+ * Zlib::BINARY
3281
+ * Zlib::ASCII
3282
+ * Zlib::UNKNOWN
3283
+ * The integers representing data types which Zlib::ZStream#data_type
3284
+ * method returns.
3285
+ *
3286
+ * Zlib::NO_COMPRESSION
3287
+ * Zlib::BEST_SPEED
3288
+ * Zlib::BEST_COMPRESSION
3289
+ * Zlib::DEFAULT_COMPRESSION
3290
+ * The integers representing compression levels which are an argument
3291
+ * for Zlib::Deflate.new, Zlib::Deflate#deflate, and so on.
3292
+ *
3293
+ * Zlib::FILTERED
3294
+ * Zlib::HUFFMAN_ONLY
3295
+ * Zlib::DEFAULT_STRATEGY
3296
+ * The integers representing compression methods which are an argument
3297
+ * for Zlib::Deflate.new and Zlib::Deflate#params.
3298
+ *
3299
+ * Zlib::DEF_MEM_LEVEL
3300
+ * Zlib::MAX_MEM_LEVEL
3301
+ * The integers representing memory levels which are an argument for
3302
+ * Zlib::Deflate.new, Zlib::Deflate#params, and so on.
3303
+ *
3304
+ * Zlib::MAX_WBITS
3305
+ * The default value of windowBits which is an argument for
3306
+ * Zlib::Deflate.new and Zlib::Inflate.new.
3307
+ *
3308
+ * Zlib::NO_FLUSH
3309
+ * Zlib::SYNC_FLUSH
3310
+ * Zlib::FULL_FLUSH
3311
+ * Zlib::FINISH
3312
+ * The integers to control the output of the deflate stream, which are
3313
+ * an argument for Zlib::Deflate#deflate and so on.
3314
+ *
3315
+ * Zlib::OS_CODE
3316
+ * Zlib::OS_MSDOS
3317
+ * Zlib::OS_AMIGA
3318
+ * Zlib::OS_VMS
3319
+ * Zlib::OS_UNIX
3320
+ * Zlib::OS_VMCMS
3321
+ * Zlib::OS_ATARI
3322
+ * Zlib::OS_OS2
3323
+ * Zlib::OS_MACOS
3324
+ * Zlib::OS_ZSYSTEM
3325
+ * Zlib::OS_CPM
3326
+ * Zlib::OS_TOPS20
3327
+ * Zlib::OS_WIN32
3328
+ * Zlib::OS_QDOS
3329
+ * Zlib::OS_RISCOS
3330
+ * Zlib::OS_UNKNOWN
3331
+ * The return values of Zlib::GzipFile#os_code method.
3332
+ */
3333
+ void Init_zlib()
3334
+ {
3335
+ VALUE mZlib, cZStream, cDeflate, cInflate;
3336
+ #if GZIP_SUPPORT
3337
+ VALUE cGzipFile, cGzipWriter, cGzipReader;
3338
+ #endif
3339
+
3340
+ mZlib = rb_define_module("Zlib");
3341
+
3342
+ cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
3343
+ cStreamEnd = rb_define_class_under(mZlib, "StreamEnd", cZError);
3344
+ cNeedDict = rb_define_class_under(mZlib, "NeedDict", cZError);
3345
+ cDataError = rb_define_class_under(mZlib, "DataError", cZError);
3346
+ cStreamError = rb_define_class_under(mZlib, "StreamError", cZError);
3347
+ cMemError = rb_define_class_under(mZlib, "MemError", cZError);
3348
+ cBufError = rb_define_class_under(mZlib, "BufError", cZError);
3349
+ cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
3350
+
3351
+ rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
3352
+ rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
3353
+ rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
3354
+ rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
3355
+
3356
+ rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
3357
+ rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
3358
+
3359
+ cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
3360
+ rb_undef_alloc_func(cZStream);
3361
+ rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
3362
+ rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
3363
+ rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
3364
+ rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
3365
+ rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
3366
+ rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
3367
+ rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
3368
+ rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
3369
+ rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
3370
+ rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
3371
+ rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
3372
+ rb_define_method(cZStream, "close", rb_zstream_end, 0);
3373
+ rb_define_method(cZStream, "end", rb_zstream_end, 0);
3374
+ rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
3375
+ rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
3376
+ rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
3377
+ rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
3378
+
3379
+ rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
3380
+ rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
3381
+ rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
3382
+
3383
+ cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
3384
+ rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
3385
+ rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
3386
+ rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
3387
+ rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
3388
+ rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
3389
+ rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
3390
+ rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
3391
+ rb_define_method(cDeflate, "params", rb_deflate_params, 2);
3392
+ rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
3393
+
3394
+ cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
3395
+ rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
3396
+ rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
3397
+ rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
3398
+ rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
3399
+ rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
3400
+ rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
3401
+ rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
3402
+ rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
3403
+
3404
+ rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
3405
+ rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
3406
+ rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
3407
+ rb_define_const(mZlib, "DEFAULT_COMPRESSION",
3408
+ INT2FIX(Z_DEFAULT_COMPRESSION));
3409
+
3410
+ rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
3411
+ rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
3412
+ rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
3413
+
3414
+ rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
3415
+ rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
3416
+ rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
3417
+
3418
+ rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
3419
+ rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
3420
+ rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
3421
+ rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
3422
+
3423
+ #if GZIP_SUPPORT
3424
+ id_write = rb_intern("write");
3425
+ id_read = rb_intern("read");
3426
+ id_flush = rb_intern("flush");
3427
+ id_seek = rb_intern("seek");
3428
+ id_close = rb_intern("close");
3429
+
3430
+ cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
3431
+ cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
3432
+
3433
+ cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
3434
+ cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
3435
+ cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
3436
+
3437
+ cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
3438
+ cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
3439
+ rb_include_module(cGzipReader, rb_mEnumerable);
3440
+
3441
+ rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
3442
+ rb_undef_alloc_func(cGzipFile);
3443
+ rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
3444
+ rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
3445
+ rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
3446
+ rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
3447
+ rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
3448
+ rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
3449
+ rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
3450
+ rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
3451
+ rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
3452
+ rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
3453
+ rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
3454
+ rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
3455
+ rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
3456
+ rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
3457
+ rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
3458
+ rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
3459
+ rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
3460
+ rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
3461
+ rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
3462
+ rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
3463
+ rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
3464
+ rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
3465
+ rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
3466
+
3467
+ rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
3468
+ rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
3469
+ rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
3470
+ rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
3471
+ rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
3472
+ rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
3473
+ rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
3474
+ rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
3475
+ rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
3476
+ rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
3477
+
3478
+ rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
3479
+ rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
3480
+ rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, 1);
3481
+ rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
3482
+ rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
3483
+ rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
3484
+ rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
3485
+ rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
3486
+ rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
3487
+ rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
3488
+ rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
3489
+ rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
3490
+ rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
3491
+ rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
3492
+ rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
3493
+
3494
+ rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
3495
+ rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
3496
+ rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
3497
+ rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
3498
+ rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
3499
+ rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
3500
+ rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
3501
+ rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
3502
+ rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
3503
+ rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
3504
+
3505
+ rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
3506
+ rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
3507
+ rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
3508
+ rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
3509
+ rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
3510
+ rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
3511
+
3512
+ #endif /* GZIP_SUPPORT */
3513
+ }
3514
+
3515
+ /* Document error classes. */
3516
+
3517
+ /*
3518
+ * Document-class: Zlib::Error
3519
+ *
3520
+ * The superclass for all exceptions raised by Ruby/zlib.
3521
+ *
3522
+ * The following exceptions are defined as subclasses of Zlib::Error. These
3523
+ * exceptions are raised when zlib library functions return with an error
3524
+ * status.
3525
+ *
3526
+ * - Zlib::StreamEnd
3527
+ * - Zlib::NeedDict
3528
+ * - Zlib::DataError
3529
+ * - Zlib::StreamError
3530
+ * - Zlib::MemError
3531
+ * - Zlib::BufError
3532
+ * - Zlib::VersionError
3533
+ *
3534
+ */
3535
+
3536
+ /*
3537
+ * Document-class: Zlib::GzipFile::Error
3538
+ *
3539
+ * Base class of errors that occur when processing GZIP files.
3540
+ */
3541
+
3542
+ /*
3543
+ * Document-class: Zlib::GzipFile::NoFooter
3544
+ *
3545
+ * Raised when gzip file footer is not found.
3546
+ */
3547
+
3548
+ /*
3549
+ * Document-class: Zlib::GzipFile::CRCError
3550
+ *
3551
+ * Raised when the CRC checksum recorded in gzip file footer is not equivalent
3552
+ * to the CRC checksum of the actual uncompressed data.
3553
+ */
3554
+
3555
+ /*
3556
+ * Document-class: Zlib::GzipFile::LengthError
3557
+ *
3558
+ * Raised when the data length recorded in the gzip file footer is not equivalent
3559
+ * to the length of the actual uncompressed data.
3560
+ */
3561
+
3562
+