Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

zlib.c
Go to the documentation of this file.
1 /*
2 * zlib.c - An interface for zlib.
3 *
4 * Copyright (C) UENO Katsuhiro 2000-2003
5 *
6 * $Id: zlib.c 41073 2013-06-04 15:44:57Z nagachika $
7 */
8
9 #include <ruby.h>
10 #include <zlib.h>
11 #include <time.h>
12 #include <ruby/io.h>
13 #include <ruby/thread.h>
14
15 #ifdef HAVE_VALGRIND_MEMCHECK_H
16 # include <valgrind/memcheck.h>
17 # ifndef VALGRIND_MAKE_MEM_DEFINED
18 # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
19 # endif
20 # ifndef VALGRIND_MAKE_MEM_UNDEFINED
21 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
22 # endif
23 #else
24 # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
25 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
26 #endif
27
28 #define RUBY_ZLIB_VERSION "0.6.0"
29
30
31 #define OBJ_IS_FREED(val) (RBASIC(val)->flags == 0)
32
33 #ifndef GZIP_SUPPORT
34 #define GZIP_SUPPORT 1
35 #endif
36
37 /* from zutil.h */
38 #ifndef DEF_MEM_LEVEL
39 #if MAX_MEM_LEVEL >= 8
40 #define DEF_MEM_LEVEL 8
41 #else
42 #define DEF_MEM_LEVEL MAX_MEM_LEVEL
43 #endif
44 #endif
45
46 #if SIZEOF_LONG > SIZEOF_INT
47 static inline uInt
48 max_uint(long n)
49 {
50 if (n > UINT_MAX) n = UINT_MAX;
51 return (uInt)n;
52 }
53 #define MAX_UINT(n) max_uint(n)
54 #else
55 #define MAX_UINT(n) (uInt)(n)
56 #endif
57
58 #define sizeof(x) ((int)sizeof(x))
59
60 static ID id_dictionaries;
61
62 /*--------- Prototypes --------*/
63
64 static NORETURN(void raise_zlib_error(int, const char*));
65 static VALUE rb_zlib_version(VALUE);
66 static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
67 static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
68 static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
69 static VALUE rb_zlib_crc_table(VALUE);
70 static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
71 static void zlib_mem_free(voidpf, voidpf);
72 static void finalizer_warn(const char*);
73
74 struct zstream;
75 struct zstream_funcs;
76 struct zstream_run_args;
77 static void zstream_init(struct zstream*, const struct zstream_funcs*);
78 static void zstream_expand_buffer(struct zstream*);
79 static void zstream_expand_buffer_into(struct zstream*, unsigned long);
80 static void zstream_append_buffer(struct zstream*, const Bytef*, long);
81 static VALUE zstream_detach_buffer(struct zstream*);
82 static VALUE zstream_shift_buffer(struct zstream*, long);
83 static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
84 static void zstream_buffer_ungetbyte(struct zstream*, int);
85 static void zstream_append_input(struct zstream*, const Bytef*, long);
86 static void zstream_discard_input(struct zstream*, long);
87 static void zstream_reset_input(struct zstream*);
88 static void zstream_passthrough_input(struct zstream*);
89 static VALUE zstream_detach_input(struct zstream*);
90 static void zstream_reset(struct zstream*);
91 static VALUE zstream_end(struct zstream*);
92 static void zstream_run(struct zstream*, Bytef*, long, int);
93 static VALUE zstream_sync(struct zstream*, Bytef*, long);
94 static void zstream_mark(struct zstream*);
95 static void zstream_free(struct zstream*);
96 static VALUE zstream_new(VALUE, const struct zstream_funcs*);
97 static struct zstream *get_zstream(VALUE);
98 static void zstream_finalize(struct zstream*);
99
100 static VALUE rb_zstream_end(VALUE);
101 static VALUE rb_zstream_reset(VALUE);
102 static VALUE rb_zstream_finish(VALUE);
103 static VALUE rb_zstream_flush_next_in(VALUE);
104 static VALUE rb_zstream_flush_next_out(VALUE);
105 static VALUE rb_zstream_avail_out(VALUE);
106 static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
107 static VALUE rb_zstream_avail_in(VALUE);
108 static VALUE rb_zstream_total_in(VALUE);
109 static VALUE rb_zstream_total_out(VALUE);
110 static VALUE rb_zstream_data_type(VALUE);
111 static VALUE rb_zstream_adler(VALUE);
112 static VALUE rb_zstream_finished_p(VALUE);
113 static VALUE rb_zstream_closed_p(VALUE);
114
115 static VALUE rb_deflate_s_allocate(VALUE);
116 static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
117 static VALUE rb_deflate_init_copy(VALUE, VALUE);
118 static VALUE deflate_run(VALUE);
119 static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
120 static void do_deflate(struct zstream*, VALUE, int);
121 static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
122 static VALUE rb_deflate_addstr(VALUE, VALUE);
123 static VALUE rb_deflate_flush(int, VALUE*, VALUE);
124 static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
125 static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
126
127 static VALUE inflate_run(VALUE);
128 static VALUE rb_inflate_s_allocate(VALUE);
129 static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
130 static VALUE rb_inflate_s_inflate(VALUE, VALUE);
131 static void do_inflate(struct zstream*, VALUE);
132 static VALUE rb_inflate_inflate(VALUE, VALUE);
133 static VALUE rb_inflate_addstr(VALUE, VALUE);
134 static VALUE rb_inflate_sync(VALUE, VALUE);
135 static VALUE rb_inflate_sync_point_p(VALUE);
136 static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
137
138 #if GZIP_SUPPORT
139 struct gzfile;
140 static void gzfile_mark(struct gzfile*);
141 static void gzfile_free(struct gzfile*);
142 static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
143 static void gzfile_reset(struct gzfile*);
144 static void gzfile_close(struct gzfile*, int);
145 static void gzfile_write_raw(struct gzfile*);
146 static VALUE gzfile_read_raw_partial(VALUE);
147 static VALUE gzfile_read_raw_rescue(VALUE);
148 static VALUE gzfile_read_raw(struct gzfile*);
149 static int gzfile_read_raw_ensure(struct gzfile*, long);
150 static char *gzfile_read_raw_until_zero(struct gzfile*, long);
151 static unsigned int gzfile_get16(const unsigned char*);
152 static unsigned long gzfile_get32(const unsigned char*);
153 static void gzfile_set32(unsigned long n, unsigned char*);
154 static void gzfile_make_header(struct gzfile*);
155 static void gzfile_make_footer(struct gzfile*);
156 static void gzfile_read_header(struct gzfile*);
157 static void gzfile_check_footer(struct gzfile*);
158 static void gzfile_write(struct gzfile*, Bytef*, long);
159 static long gzfile_read_more(struct gzfile*);
160 static void gzfile_calc_crc(struct gzfile*, VALUE);
161 static VALUE gzfile_read(struct gzfile*, long);
162 static VALUE gzfile_read_all(struct gzfile*);
163 static void gzfile_ungets(struct gzfile*, const Bytef*, long);
164 static void gzfile_ungetbyte(struct gzfile*, int);
165 static VALUE gzfile_writer_end_run(VALUE);
166 static void gzfile_writer_end(struct gzfile*);
167 static VALUE gzfile_reader_end_run(VALUE);
168 static void gzfile_reader_end(struct gzfile*);
169 static void gzfile_reader_rewind(struct gzfile*);
170 static VALUE gzfile_reader_get_unused(struct gzfile*);
171 static struct gzfile *get_gzfile(VALUE);
172 static VALUE gzfile_ensure_close(VALUE);
173 static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
174 static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
175 NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *));
176 static VALUE gzfile_error_inspect(VALUE);
177
178 static VALUE rb_gzfile_to_io(VALUE);
179 static VALUE rb_gzfile_crc(VALUE);
180 static VALUE rb_gzfile_mtime(VALUE);
181 static VALUE rb_gzfile_level(VALUE);
182 static VALUE rb_gzfile_os_code(VALUE);
183 static VALUE rb_gzfile_orig_name(VALUE);
184 static VALUE rb_gzfile_comment(VALUE);
185 static VALUE rb_gzfile_lineno(VALUE);
186 static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
187 static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
188 static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
189 static VALUE rb_gzfile_set_comment(VALUE, VALUE);
190 static VALUE rb_gzfile_close(VALUE);
191 static VALUE rb_gzfile_finish(VALUE);
192 static VALUE rb_gzfile_closed_p(VALUE);
193 static VALUE rb_gzfile_eof_p(VALUE);
194 static VALUE rb_gzfile_sync(VALUE);
195 static VALUE rb_gzfile_set_sync(VALUE, VALUE);
196 static VALUE rb_gzfile_total_in(VALUE);
197 static VALUE rb_gzfile_total_out(VALUE);
198 static VALUE rb_gzfile_path(VALUE);
199
200 static VALUE rb_gzwriter_s_allocate(VALUE);
201 static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
202 static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
203 static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
204 static VALUE rb_gzwriter_write(VALUE, VALUE);
205 static VALUE rb_gzwriter_putc(VALUE, VALUE);
206
207 static VALUE rb_gzreader_s_allocate(VALUE);
208 static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
209 static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
210 static VALUE rb_gzreader_rewind(VALUE);
211 static VALUE rb_gzreader_unused(VALUE);
212 static VALUE rb_gzreader_read(int, VALUE*, VALUE);
213 static VALUE rb_gzreader_getc(VALUE);
214 static VALUE rb_gzreader_readchar(VALUE);
215 static VALUE rb_gzreader_each_byte(VALUE);
216 static VALUE rb_gzreader_ungetc(VALUE, VALUE);
217 static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
218 static void gzreader_skip_linebreaks(struct gzfile*);
219 static VALUE gzreader_gets(int, VALUE*, VALUE);
220 static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
221 static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
222 static VALUE rb_gzreader_each(int, VALUE*, VALUE);
223 static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
224 #endif /* GZIP_SUPPORT */
225
226 /*
227 * Document-module: Zlib
228 *
229 * This module provides access to the {zlib library}[http://zlib.net]. Zlib is
230 * designed to be a portable, free, general-purpose, legally unencumbered --
231 * that is, not covered by any patents -- lossless data-compression library
232 * for use on virtually any computer hardware and operating system.
233 *
234 * The zlib compression library provides in-memory compression and
235 * decompression functions, including integrity checks of the uncompressed
236 * data.
237 *
238 * The zlib compressed data format is described in RFC 1950, which is a
239 * wrapper around a deflate stream which is described in RFC 1951.
240 *
241 * The library also supports reading and writing files in gzip (.gz) format
242 * with an interface similar to that of IO. The gzip format is described in
243 * RFC 1952 which is also a wrapper around a deflate stream.
244 *
245 * The zlib format was designed to be compact and fast for use in memory and on
246 * communications channels. The gzip format was designed for single-file
247 * compression on file systems, has a larger header than zlib to maintain
248 * directory information, and uses a different, slower check method than zlib.
249 *
250 * See your system's zlib.h for further information about zlib
251 *
252 * == Sample usage
253 *
254 * Using the wrapper to compress strings with default parameters is quite
255 * simple:
256 *
257 * require "zlib"
258 *
259 * data_to_compress = File.read("don_quixote.txt")
260 *
261 * puts "Input size: #{data_to_compress.size}"
262 * #=> Input size: 2347740
263 *
264 * data_compressed = Zlib::Deflate.deflate(data_to_compress)
265 *
266 * puts "Compressed size: #{data_compressed.size}"
267 * #=> Compressed size: 887238
268 *
269 * uncompressed_data = Zlib::Inflate.inflate(data_compressed)
270 *
271 * puts "Uncompressed data is: #{uncompressed_data}"
272 * #=> Uncompressed data is: The Project Gutenberg EBook of Don Quixote...
273 *
274 * == Class tree
275 *
276 * - Zlib::Deflate
277 * - Zlib::Inflate
278 * - Zlib::ZStream
279 * - Zlib::Error
280 * - Zlib::StreamEnd
281 * - Zlib::NeedDict
282 * - Zlib::DataError
283 * - Zlib::StreamError
284 * - Zlib::MemError
285 * - Zlib::BufError
286 * - Zlib::VersionError
287 *
288 * (if you have GZIP_SUPPORT)
289 * - Zlib::GzipReader
290 * - Zlib::GzipWriter
291 * - Zlib::GzipFile
292 * - Zlib::GzipFile::Error
293 * - Zlib::GzipFile::LengthError
294 * - Zlib::GzipFile::CRCError
295 * - Zlib::GzipFile::NoFooter
296 *
297 */
298 void Init_zlib(void);
299
300 /*--------- Exceptions --------*/
301
302 static VALUE cZError, cStreamEnd, cNeedDict;
303 static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
304
305 static void
306 raise_zlib_error(int err, const char *msg)
307 {
308 VALUE exc;
309
310 if (!msg) {
311 msg = zError(err);
312 }
313
314 switch(err) {
315 case Z_STREAM_END:
316 exc = rb_exc_new2(cStreamEnd, msg);
317 break;
318 case Z_NEED_DICT:
319 exc = rb_exc_new2(cNeedDict, msg);
320 break;
321 case Z_STREAM_ERROR:
322 exc = rb_exc_new2(cStreamError, msg);
323 break;
324 case Z_DATA_ERROR:
325 exc = rb_exc_new2(cDataError, msg);
326 break;
327 case Z_BUF_ERROR:
328 exc = rb_exc_new2(cBufError, msg);
329 break;
330 case Z_VERSION_ERROR:
331 exc = rb_exc_new2(cVersionError, msg);
332 break;
333 case Z_MEM_ERROR:
334 exc = rb_exc_new2(cMemError, msg);
335 break;
336 case Z_ERRNO:
337 rb_sys_fail(msg);
338 /* no return */
339 default:
340 {
341 char buf[BUFSIZ];
342 snprintf(buf, BUFSIZ, "unknown zlib error %d: %s", err, msg);
343 exc = rb_exc_new2(cZError, buf);
344 }
345 }
346
347 rb_exc_raise(exc);
348 }
349
350
351 /*--- Warning (in finalizer) ---*/
352
353 static void
354 finalizer_warn(const char *msg)
355 {
356 fprintf(stderr, "zlib(finalizer): %s\n", msg);
357 }
358
359
360 /*-------- module Zlib --------*/
361
362 /*
363 * Document-method: Zlib.zlib_version
364 *
365 * Returns the string which represents the version of zlib library.
366 */
367 static VALUE
368 rb_zlib_version(VALUE klass)
369 {
370 VALUE str;
371
372 str = rb_str_new2(zlibVersion());
373 OBJ_TAINT(str); /* for safe */
374 return str;
375 }
376
377 #if SIZEOF_LONG > SIZEOF_INT
378 static uLong
379 checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
380 {
381 if (len > UINT_MAX) {
382 do {
383 sum = func(sum, ptr, UINT_MAX);
384 ptr += UINT_MAX;
385 len -= UINT_MAX;
386 } while (len >= UINT_MAX);
387 }
388 if (len > 0) sum = func(sum, ptr, (uInt)len);
389 return sum;
390 }
391 #else
392 #define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
393 #endif
394
395 static VALUE
396 do_checksum(argc, argv, func)
397 int argc;
398 VALUE *argv;
399 uLong (*func)(uLong, const Bytef*, uInt);
400 {
401 VALUE str, vsum;
402 unsigned long sum;
403
404 rb_scan_args(argc, argv, "02", &str, &vsum);
405
406 if (!NIL_P(vsum)) {
407 sum = NUM2ULONG(vsum);
408 }
409 else if (NIL_P(str)) {
410 sum = 0;
411 }
412 else {
413 sum = func(0, Z_NULL, 0);
414 }
415
416 if (NIL_P(str)) {
417 sum = func(sum, Z_NULL, 0);
418 }
419 else {
420 StringValue(str);
421 sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
422 }
423 return rb_uint2inum(sum);
424 }
425
426 /*
427 * Document-method: Zlib.adler32
428 *
429 * call-seq: Zlib.adler32(string, adler)
430 *
431 * Calculates Adler-32 checksum for +string+, and returns updated value of
432 * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
433 * +adler+ is omitted, it assumes that the initial value is given to +adler+.
434 *
435 * FIXME: expression.
436 */
437 static VALUE
438 rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
439 {
440 return do_checksum(argc, argv, adler32);
441 }
442
443 #ifdef HAVE_ADLER32_COMBINE
444 /*
445 * Document-method: Zlib.adler32_combine
446 *
447 * call-seq: Zlib.adler32_combine(adler1, adler2, len2)
448 *
449 * Combine two Adler-32 check values in to one. +alder1+ is the first Adler-32
450 * value, +adler2+ is the second Adler-32 value. +len2+ is the length of the
451 * string used to generate +adler2+.
452 *
453 */
454 static VALUE
455 rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
456 {
457 return ULONG2NUM(
458 adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
459 }
460 #else
461 #define rb_zlib_adler32_combine rb_f_notimplement
462 #endif
463
464 /*
465 * Document-method: Zlib.crc32
466 *
467 * call-seq: Zlib.crc32(string, adler)
468 *
469 * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
470 * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
471 * assumes that the initial value is given to +crc+.
472 *
473 * FIXME: expression.
474 */
475 static VALUE
476 rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
477 {
478 return do_checksum(argc, argv, crc32);
479 }
480
481 #ifdef HAVE_CRC32_COMBINE
482 /*
483 * Document-method: Zlib.crc32_combine
484 *
485 * call-seq: Zlib.crc32_combine(crc1, crc2, len2)
486 *
487 * Combine two CRC-32 check values in to one. +crc1+ is the first CRC-32
488 * value, +crc2+ is the second CRC-32 value. +len2+ is the length of the
489 * string used to generate +crc2+.
490 *
491 */
492 static VALUE
493 rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
494 {
495 return ULONG2NUM(
496 crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
497 }
498 #else
499 #define rb_zlib_crc32_combine rb_f_notimplement
500 #endif
501
502 /*
503 * Document-method: Zlib.crc_table
504 *
505 * Returns the table for calculating CRC checksum as an array.
506 */
507 static VALUE
508 rb_zlib_crc_table(VALUE obj)
509 {
510 #if !defined(HAVE_TYPE_Z_CRC_T)
511 /* z_crc_t is defined since zlib-1.2.7. */
512 typedef unsigned long z_crc_t;
513 #endif
514 const z_crc_t *crctbl;
515 VALUE dst;
516 int i;
517
518 crctbl = get_crc_table();
519 dst = rb_ary_new2(256);
520
521 for (i = 0; i < 256; i++) {
522 rb_ary_push(dst, rb_uint2inum(crctbl[i]));
523 }
524 return dst;
525 }
526
527
528
529 /*-------- zstream - internal APIs --------*/
530
531 struct zstream {
532 unsigned long flags;
533 VALUE buf;
534 long buf_filled;
535 VALUE input;
536 z_stream stream;
537 const struct zstream_funcs {
538 int (*reset)(z_streamp);
539 int (*end)(z_streamp);
540 int (*run)(z_streamp, int);
541 } *func;
542 };
543
544 #define ZSTREAM_FLAG_READY 0x1
545 #define ZSTREAM_FLAG_IN_STREAM 0x2
546 #define ZSTREAM_FLAG_FINISHED 0x4
547 #define ZSTREAM_FLAG_CLOSING 0x8
548 #define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for
549 gzip*/
550 #define ZSTREAM_FLAG_UNUSED 0x20
551
552 #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
553 #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
554 #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
555 #define ZSTREAM_IS_CLOSING(z) ((z)->flags & ZSTREAM_FLAG_CLOSING)
556 #define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE)
557
558 #define ZSTREAM_EXPAND_BUFFER_OK 0
559
560 /* I think that more better value should be found,
561 but I gave up finding it. B) */
562 #define ZSTREAM_INITIAL_BUFSIZE 1024
563 /* Allow a quick return when the thread is interrupted */
564 #define ZSTREAM_AVAIL_OUT_STEP_MAX 16384
565 #define ZSTREAM_AVAIL_OUT_STEP_MIN 2048
566
567 static const struct zstream_funcs deflate_funcs = {
568 deflateReset, deflateEnd, deflate,
569 };
570
571 static const struct zstream_funcs inflate_funcs = {
572 inflateReset, inflateEnd, inflate,
573 };
574
575 struct zstream_run_args {
576 struct zstream * z;
577 int flush; /* stream flush value for inflate() or deflate() */
578 int interrupt; /* stop processing the stream and return to ruby */
579 int jump_state; /* for buffer expansion block break or exception */
580 int stream_output; /* for streaming zlib processing */
581 };
582
583 static voidpf
584 zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
585 {
586 voidpf p = xmalloc(items * size);
587 /* zlib FAQ: Valgrind (or some similar memory access checker) says that
588 deflate is performing a conditional jump that depends on an
589 uninitialized value. Isn't that a bug?
590 http://www.zlib.net/zlib_faq.html#faq36 */
591 (void)VALGRIND_MAKE_MEM_DEFINED(p, items * size);
592 return p;
593 }
594
595 static void
596 zlib_mem_free(voidpf opaque, voidpf address)
597 {
598 xfree(address);
599 }
600
601 static void
602 zstream_init(struct zstream *z, const struct zstream_funcs *func)
603 {
604 z->flags = 0;
605 z->buf = Qnil;
606 z->buf_filled = 0;
607 z->input = Qnil;
608 z->stream.zalloc = zlib_mem_alloc;
609 z->stream.zfree = zlib_mem_free;
610 z->stream.opaque = Z_NULL;
611 z->stream.msg = Z_NULL;
612 z->stream.next_in = Z_NULL;
613 z->stream.avail_in = 0;
614 z->stream.next_out = Z_NULL;
615 z->stream.avail_out = 0;
616 z->func = func;
617 }
618
619 #define zstream_init_deflate(z) zstream_init((z), &deflate_funcs)
620 #define zstream_init_inflate(z) zstream_init((z), &inflate_funcs)
621
622 static void
623 zstream_expand_buffer(struct zstream *z)
624 {
625 if (NIL_P(z->buf)) {
626 zstream_expand_buffer_into(z, ZSTREAM_INITIAL_BUFSIZE);
627 return;
628 }
629
630 if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
631 if (z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
632 int state = 0;
633 VALUE self = (VALUE)z->stream.opaque;
634
635 rb_str_resize(z->buf, z->buf_filled);
636 RBASIC(z->buf)->klass = rb_cString;
637 OBJ_INFECT(z->buf, self);
638
639 rb_protect(rb_yield, z->buf, &state);
640
641 z->buf = Qnil;
642 zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
643
644 if (state)
645 rb_jump_tag(state);
646
647 return;
648 }
649 else {
650 zstream_expand_buffer_into(z,
651 ZSTREAM_AVAIL_OUT_STEP_MAX - z->buf_filled);
652 }
653 }
654 else {
655 if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
656 z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
657 }
658 else {
659 long inc = z->buf_filled / 2;
660 if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
661 inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
662 }
663 rb_str_resize(z->buf, z->buf_filled + inc);
664 z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
665 (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
666 }
667 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
668 }
669 }
670
671 static void
672 zstream_expand_buffer_into(struct zstream *z, unsigned long size)
673 {
674 if (NIL_P(z->buf)) {
675 /* I uses rb_str_new here not rb_str_buf_new because
676 rb_str_buf_new makes a zero-length string. */
677 z->buf = rb_str_new(0, size);
678 z->buf_filled = 0;
679 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
680 z->stream.avail_out = MAX_UINT(size);
681 RBASIC(z->buf)->klass = 0;
682 }
683 else if (z->stream.avail_out != size) {
684 rb_str_resize(z->buf, z->buf_filled + size);
685 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
686 z->stream.avail_out = MAX_UINT(size);
687 }
688 }
689
690 static void *
691 zstream_expand_buffer_protect(void *ptr)
692 {
693 struct zstream *z = (struct zstream *)ptr;
694 int state = 0;
695
696 rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
697
698 return (void *)(VALUE)state;
699 }
700
701 static int
702 zstream_expand_buffer_without_gvl(struct zstream *z)
703 {
704 char * new_str;
705 long inc, len;
706
707 if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
708 z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
709 }
710 else {
711 inc = z->buf_filled / 2;
712 if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
713 inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
714 }
715
716 len = z->buf_filled + inc;
717
718 new_str = ruby_xrealloc(RSTRING(z->buf)->as.heap.ptr, len + 1);
719
720 /* from rb_str_resize */
721 RSTRING(z->buf)->as.heap.ptr = new_str;
722 RSTRING(z->buf)->as.heap.ptr[len] = '\0'; /* sentinel */
723 RSTRING(z->buf)->as.heap.len =
724 RSTRING(z->buf)->as.heap.aux.capa = len;
725
726 z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
727 (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
728 }
729 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
730
731 return ZSTREAM_EXPAND_BUFFER_OK;
732 }
733
734 static void
735 zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
736 {
737 if (NIL_P(z->buf)) {
738 z->buf = rb_str_buf_new(len);
739 rb_str_buf_cat(z->buf, (const char*)src, len);
740 z->buf_filled = len;
741 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
742 z->stream.avail_out = 0;
743 RBASIC(z->buf)->klass = 0;
744 return;
745 }
746
747 if (RSTRING_LEN(z->buf) < z->buf_filled + len) {
748 rb_str_resize(z->buf, z->buf_filled + len);
749 z->stream.avail_out = 0;
750 }
751 else {
752 if (z->stream.avail_out >= (uInt)len) {
753 z->stream.avail_out -= (uInt)len;
754 }
755 else {
756 z->stream.avail_out = 0;
757 }
758 }
759 memcpy(RSTRING_PTR(z->buf) + z->buf_filled, src, len);
760 z->buf_filled += len;
761 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
762 }
763
764 #define zstream_append_buffer2(z,v) \
765 zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v))
766
767 static VALUE
768 zstream_detach_buffer(struct zstream *z)
769 {
770 VALUE dst, self = (VALUE)z->stream.opaque;
771
772 if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
773 rb_block_given_p()) {
774 /* prevent tiny yields mid-stream, save for next
775 * zstream_expand_buffer() or stream end */
776 return Qnil;
777 }
778
779 if (NIL_P(z->buf)) {
780 dst = rb_str_new(0, 0);
781 }
782 else {
783 dst = z->buf;
784 rb_str_resize(dst, z->buf_filled);
785 RBASIC(dst)->klass = rb_cString;
786 }
787
788 OBJ_INFECT(dst, self);
789
790 z->buf = Qnil;
791 z->buf_filled = 0;
792 z->stream.next_out = 0;
793 z->stream.avail_out = 0;
794
795 if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
796 rb_yield(dst);
797 dst = Qnil;
798 }
799
800 return dst;
801 }
802
803 static VALUE
804 zstream_shift_buffer(struct zstream *z, long len)
805 {
806 VALUE dst;
807 long buflen;
808
809 if (z->buf_filled <= len) {
810 return zstream_detach_buffer(z);
811 }
812
813 dst = rb_str_subseq(z->buf, 0, len);
814 RBASIC(dst)->klass = rb_cString;
815 z->buf_filled -= len;
816 memmove(RSTRING_PTR(z->buf), RSTRING_PTR(z->buf) + len,
817 z->buf_filled);
818 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
819 buflen = RSTRING_LEN(z->buf) - z->buf_filled;
820 if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
821 buflen = ZSTREAM_AVAIL_OUT_STEP_MAX;
822 }
823 z->stream.avail_out = (uInt)buflen;
824
825 return dst;
826 }
827
828 static void
829 zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
830 {
831 if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
832 zstream_expand_buffer_into(z, len);
833 }
834
835 memmove(RSTRING_PTR(z->buf) + len, RSTRING_PTR(z->buf), z->buf_filled);
836 memmove(RSTRING_PTR(z->buf), b, len);
837 z->buf_filled+=len;
838 if (z->stream.avail_out > 0) {
839 if (len > z->stream.avail_out) len = z->stream.avail_out;
840 z->stream.next_out+=len;
841 z->stream.avail_out-=(uInt)len;
842 }
843 }
844
845 static void
846 zstream_buffer_ungetbyte(struct zstream *z, int c)
847 {
848 if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
849 zstream_expand_buffer(z);
850 }
851
852 memmove(RSTRING_PTR(z->buf) + 1, RSTRING_PTR(z->buf), z->buf_filled);
853 RSTRING_PTR(z->buf)[0] = (char)c;
854 z->buf_filled++;
855 if (z->stream.avail_out > 0) {
856 z->stream.next_out++;
857 z->stream.avail_out--;
858 }
859 }
860
861 static void
862 zstream_append_input(struct zstream *z, const Bytef *src, long len)
863 {
864 if (len <= 0) return;
865
866 if (NIL_P(z->input)) {
867 z->input = rb_str_buf_new(len);
868 rb_str_buf_cat(z->input, (const char*)src, len);
869 RBASIC(z->input)->klass = 0;
870 }
871 else {
872 rb_str_buf_cat(z->input, (const char*)src, len);
873 }
874 }
875
876 #define zstream_append_input2(z,v)\
877 RB_GC_GUARD(v),\
878 zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
879
880 static void
881 zstream_discard_input(struct zstream *z, long len)
882 {
883 if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) {
884 z->input = Qnil;
885 }
886 else {
887 memmove(RSTRING_PTR(z->input), RSTRING_PTR(z->input) + len,
888 RSTRING_LEN(z->input) - len);
889 rb_str_resize(z->input, RSTRING_LEN(z->input) - len);
890 }
891 }
892
893 static void
894 zstream_reset_input(struct zstream *z)
895 {
896 z->input = Qnil;
897 }
898
899 static void
900 zstream_passthrough_input(struct zstream *z)
901 {
902 if (!NIL_P(z->input)) {
903 zstream_append_buffer2(z, z->input);
904 z->input = Qnil;
905 }
906 }
907
908 static VALUE
909 zstream_detach_input(struct zstream *z)
910 {
911 VALUE dst;
912
913 if (NIL_P(z->input)) {
914 dst = rb_str_new(0, 0);
915 }
916 else {
917 dst = z->input;
918 RBASIC(dst)->klass = rb_cString;
919 }
920 z->input = Qnil;
921 RBASIC(dst)->klass = rb_cString;
922 return dst;
923 }
924
925 static void
926 zstream_reset(struct zstream *z)
927 {
928 int err;
929
930 err = z->func->reset(&z->stream);
931 if (err != Z_OK) {
932 raise_zlib_error(err, z->stream.msg);
933 }
934 z->flags = ZSTREAM_FLAG_READY;
935 z->buf = Qnil;
936 z->buf_filled = 0;
937 z->stream.next_out = 0;
938 z->stream.avail_out = 0;
939 zstream_reset_input(z);
940 }
941
942 static VALUE
943 zstream_end(struct zstream *z)
944 {
945 int err;
946
947 if (!ZSTREAM_IS_READY(z)) {
948 rb_warning("attempt to close uninitialized zstream; ignored.");
949 return Qnil;
950 }
951 if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
952 rb_warning("attempt to close unfinished zstream; reset forced.");
953 zstream_reset(z);
954 }
955
956 zstream_reset_input(z);
957 err = z->func->end(&z->stream);
958 if (err != Z_OK) {
959 raise_zlib_error(err, z->stream.msg);
960 }
961 z->flags = 0;
962 return Qnil;
963 }
964
965 static void *
966 zstream_run_func(void *ptr)
967 {
968 struct zstream_run_args *args = (struct zstream_run_args *)ptr;
969 int err, state, flush = args->flush;
970 struct zstream *z = args->z;
971 uInt n;
972
973 err = Z_OK;
974 while (!args->interrupt) {
975 n = z->stream.avail_out;
976 err = z->func->run(&z->stream, flush);
977 z->buf_filled += n - z->stream.avail_out;
978
979 if (err == Z_STREAM_END) {
980 z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
981 z->flags |= ZSTREAM_FLAG_FINISHED;
982 break;
983 }
984
985 if (err != Z_OK && err != Z_BUF_ERROR)
986 break;
987
988 if (z->stream.avail_out > 0) {
989 z->flags |= ZSTREAM_FLAG_IN_STREAM;
990 break;
991 }
992
993 if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
994 /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
995 /* but deflate() could be called with avail_in == 0 (there's hidden buffer
996 in zstream->state) */
997 z->flags |= ZSTREAM_FLAG_IN_STREAM;
998 break;
999 }
1000
1001 if (args->stream_output) {
1002 state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
1003 (void *)z);
1004 } else {
1005 state = zstream_expand_buffer_without_gvl(z);
1006 }
1007
1008 if (state) {
1009 err = Z_OK; /* buffer expanded but stream processing was stopped */
1010 args->jump_state = state;
1011 break;
1012 }
1013 }
1014
1015 return (void *)(VALUE)err;
1016 }
1017
1018 /*
1019 * There is no safe way to interrupt z->run->func().
1020 */
1021 static void
1022 zstream_unblock_func(void *ptr)
1023 {
1024 struct zstream_run_args *args = (struct zstream_run_args *)ptr;
1025
1026 args->interrupt = 1;
1027 }
1028
1029 static void
1030 zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1031 {
1032 struct zstream_run_args args;
1033 int err;
1034 volatile VALUE guard = Qnil;
1035
1036 args.z = z;
1037 args.flush = flush;
1038 args.interrupt = 0;
1039 args.jump_state = 0;
1040 args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
1041
1042 if (NIL_P(z->input) && len == 0) {
1043 z->stream.next_in = (Bytef*)"";
1044 z->stream.avail_in = 0;
1045 }
1046 else {
1047 zstream_append_input(z, src, len);
1048 z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1049 z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1050 /* keep reference to `z->input' so as not to be garbage collected
1051 after zstream_reset_input() and prevent `z->stream.next_in'
1052 from dangling. */
1053 guard = z->input;
1054 }
1055
1056 if (z->stream.avail_out == 0) {
1057 zstream_expand_buffer(z);
1058 }
1059
1060 loop:
1061 err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
1062 zstream_unblock_func, (void *)&args);
1063
1064 if (flush != Z_FINISH && err == Z_BUF_ERROR
1065 && z->stream.avail_out > 0) {
1066 z->flags |= ZSTREAM_FLAG_IN_STREAM;
1067 }
1068
1069 zstream_reset_input(z);
1070
1071 if (err != Z_OK && err != Z_STREAM_END) {
1072 if (z->stream.avail_in > 0) {
1073 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1074 }
1075 if (err == Z_NEED_DICT) {
1076 VALUE self = (VALUE)z->stream.opaque;
1077 VALUE dicts = rb_ivar_get(self, id_dictionaries);
1078 VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
1079 if (!NIL_P(dict)) {
1080 rb_inflate_set_dictionary(self, dict);
1081 goto loop;
1082 }
1083 }
1084 raise_zlib_error(err, z->stream.msg);
1085 }
1086
1087 if (z->stream.avail_in > 0) {
1088 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1089 RB_GC_GUARD(guard) = Qnil; /* prevent tail call to make guard effective */
1090 }
1091
1092 if (args.jump_state)
1093 rb_jump_tag(args.jump_state);
1094 }
1095
1096 static VALUE
1097 zstream_sync(struct zstream *z, Bytef *src, long len)
1098 {
1099 /* VALUE rest; */
1100 int err;
1101
1102 if (!NIL_P(z->input)) {
1103 z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1104 z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1105 err = inflateSync(&z->stream);
1106 if (err == Z_OK) {
1107 zstream_discard_input(z,
1108 RSTRING_LEN(z->input) - z->stream.avail_in);
1109 zstream_append_input(z, src, len);
1110 return Qtrue;
1111 }
1112 zstream_reset_input(z);
1113 if (err != Z_DATA_ERROR) {
1114 /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1115 raise_zlib_error(err, z->stream.msg);
1116 }
1117 }
1118
1119 if (len <= 0) return Qfalse;
1120
1121 z->stream.next_in = src;
1122 z->stream.avail_in = MAX_UINT(len);
1123 err = inflateSync(&z->stream);
1124 if (err == Z_OK) {
1125 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1126 return Qtrue;
1127 }
1128 if (err != Z_DATA_ERROR) {
1129 /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1130 raise_zlib_error(err, z->stream.msg);
1131 }
1132 return Qfalse;
1133 }
1134
1135 static void
1136 zstream_mark(struct zstream *z)
1137 {
1138 rb_gc_mark(z->buf);
1139 rb_gc_mark(z->input);
1140 }
1141
1142 static void
1143 zstream_finalize(struct zstream *z)
1144 {
1145 int err = z->func->end(&z->stream);
1146 if (err == Z_STREAM_ERROR)
1147 finalizer_warn("the stream state was inconsistent.");
1148 if (err == Z_DATA_ERROR)
1149 finalizer_warn("the stream was freed prematurely.");
1150 }
1151
1152 static void
1153 zstream_free(struct zstream *z)
1154 {
1155 if (ZSTREAM_IS_READY(z)) {
1156 zstream_finalize(z);
1157 }
1158 xfree(z);
1159 }
1160
1161 static VALUE
1162 zstream_new(VALUE klass, const struct zstream_funcs *funcs)
1163 {
1164 VALUE obj;
1165 struct zstream *z;
1166
1167 obj = Data_Make_Struct(klass, struct zstream,
1168 zstream_mark, zstream_free, z);
1169 zstream_init(z, funcs);
1170 z->stream.opaque = (voidpf)obj;
1171 return obj;
1172 }
1173
1174 #define zstream_deflate_new(klass) zstream_new((klass), &deflate_funcs)
1175 #define zstream_inflate_new(klass) zstream_new((klass), &inflate_funcs)
1176
1177 static struct zstream *
1178 get_zstream(VALUE obj)
1179 {
1180 struct zstream *z;
1181
1182 Data_Get_Struct(obj, struct zstream, z);
1183 if (!ZSTREAM_IS_READY(z)) {
1184 rb_raise(cZError, "stream is not ready");
1185 }
1186 return z;
1187 }
1188
1189
1190 /* ------------------------------------------------------------------------- */
1191
1192 /*
1193 * Document-class: Zlib::ZStream
1194 *
1195 * Zlib::ZStream is the abstract class for the stream which handles the
1196 * compressed data. The operations are defined in the subclasses:
1197 * Zlib::Deflate for compression, and Zlib::Inflate for decompression.
1198 *
1199 * An instance of Zlib::ZStream has one stream (struct zstream in the source)
1200 * and two variable-length buffers which associated to the input (next_in) of
1201 * the stream and the output (next_out) of the stream. In this document,
1202 * "input buffer" means the buffer for input, and "output buffer" means the
1203 * buffer for output.
1204 *
1205 * Data input into an instance of Zlib::ZStream are temporally stored into
1206 * the end of input buffer, and then data in input buffer are processed from
1207 * the beginning of the buffer until no more output from the stream is
1208 * produced (i.e. until avail_out > 0 after processing). During processing,
1209 * output buffer is allocated and expanded automatically to hold all output
1210 * data.
1211 *
1212 * Some particular instance methods consume the data in output buffer and
1213 * return them as a String.
1214 *
1215 * Here is an ascii art for describing above:
1216 *
1217 * +================ an instance of Zlib::ZStream ================+
1218 * || ||
1219 * || +--------+ +-------+ +--------+ ||
1220 * || +--| output |<---------|zstream|<---------| input |<--+ ||
1221 * || | | buffer | next_out+-------+next_in | buffer | | ||
1222 * || | +--------+ +--------+ | ||
1223 * || | | ||
1224 * +===|======================================================|===+
1225 * | |
1226 * v |
1227 * "output data" "input data"
1228 *
1229 * If an error occurs during processing input buffer, an exception which is a
1230 * subclass of Zlib::Error is raised. At that time, both input and output
1231 * buffer keep their conditions at the time when the error occurs.
1232 *
1233 * == Method Catalogue
1234 *
1235 * Many of the methods in this class are fairly low-level and unlikely to be
1236 * of interest to users. In fact, users are unlikely to use this class
1237 * directly; rather they will be interested in Zlib::Inflate and
1238 * Zlib::Deflate.
1239 *
1240 * The higher level methods are listed below.
1241 *
1242 * - #total_in
1243 * - #total_out
1244 * - #data_type
1245 * - #adler
1246 * - #reset
1247 * - #finish
1248 * - #finished?
1249 * - #close
1250 * - #closed?
1251 */
1252
1253 /*
1254 * Closes the stream. All operations on the closed stream will raise an
1255 * exception.
1256 */
1257 static VALUE
1258 rb_zstream_end(VALUE obj)
1259 {
1260 zstream_end(get_zstream(obj));
1261 return Qnil;
1262 }
1263
1264 /*
1265 * Resets and initializes the stream. All data in both input and output buffer
1266 * are discarded.
1267 */
1268 static VALUE
1269 rb_zstream_reset(VALUE obj)
1270 {
1271 zstream_reset(get_zstream(obj));
1272 return Qnil;
1273 }
1274
1275 /*
1276 * call-seq:
1277 * finish -> String
1278 * finish { |chunk| ... } -> nil
1279 *
1280 * Finishes the stream and flushes output buffer. If a block is given each
1281 * chunk is yielded to the block until the input buffer has been flushed to
1282 * the output buffer.
1283 */
1284 static VALUE
1285 rb_zstream_finish(VALUE obj)
1286 {
1287 struct zstream *z = get_zstream(obj);
1288
1289 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1290
1291 return zstream_detach_buffer(z);
1292 }
1293
1294 /*
1295 * call-seq:
1296 * flush_next_out -> String
1297 * flush_next_out { |chunk| ... } -> nil
1298 *
1299 * Flushes output buffer and returns all data in that buffer. If a block is
1300 * given each chunk is yielded to the block until the current output buffer
1301 * has been flushed.
1302 */
1303 static VALUE
1304 rb_zstream_flush_next_in(VALUE obj)
1305 {
1306 struct zstream *z;
1307 VALUE dst;
1308
1309 Data_Get_Struct(obj, struct zstream, z);
1310 dst = zstream_detach_input(z);
1311 OBJ_INFECT(dst, obj);
1312 return dst;
1313 }
1314
1315 /*
1316 * Flushes output buffer and returns all data in that buffer.
1317 */
1318 static VALUE
1319 rb_zstream_flush_next_out(VALUE obj)
1320 {
1321 struct zstream *z;
1322
1323 Data_Get_Struct(obj, struct zstream, z);
1324
1325 return zstream_detach_buffer(z);
1326 }
1327
1328 /*
1329 * Returns number of bytes of free spaces in output buffer. Because the free
1330 * space is allocated automatically, this method returns 0 normally.
1331 */
1332 static VALUE
1333 rb_zstream_avail_out(VALUE obj)
1334 {
1335 struct zstream *z;
1336 Data_Get_Struct(obj, struct zstream, z);
1337 return rb_uint2inum(z->stream.avail_out);
1338 }
1339
1340 /*
1341 * Allocates +size+ bytes of free space in the output buffer. If there are more
1342 * than +size+ bytes already in the buffer, the buffer is truncated. Because
1343 * free space is allocated automatically, you usually don't need to use this
1344 * method.
1345 */
1346 static VALUE
1347 rb_zstream_set_avail_out(VALUE obj, VALUE size)
1348 {
1349 struct zstream *z = get_zstream(obj);
1350
1351 Check_Type(size, T_FIXNUM);
1352 zstream_expand_buffer_into(z, FIX2INT(size));
1353 return size;
1354 }
1355
1356 /*
1357 * Returns bytes of data in the input buffer. Normally, returns 0.
1358 */
1359 static VALUE
1360 rb_zstream_avail_in(VALUE obj)
1361 {
1362 struct zstream *z;
1363 Data_Get_Struct(obj, struct zstream, z);
1364 return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING_LEN(z->input)));
1365 }
1366
1367 /*
1368 * Returns the total bytes of the input data to the stream. FIXME
1369 */
1370 static VALUE
1371 rb_zstream_total_in(VALUE obj)
1372 {
1373 return rb_uint2inum(get_zstream(obj)->stream.total_in);
1374 }
1375
1376 /*
1377 * Returns the total bytes of the output data from the stream. FIXME
1378 */
1379 static VALUE
1380 rb_zstream_total_out(VALUE obj)
1381 {
1382 return rb_uint2inum(get_zstream(obj)->stream.total_out);
1383 }
1384
1385 /*
1386 * Guesses the type of the data which have been inputed into the stream. The
1387 * returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
1388 * <tt>UNKNOWN</tt>.
1389 */
1390 static VALUE
1391 rb_zstream_data_type(VALUE obj)
1392 {
1393 return INT2FIX(get_zstream(obj)->stream.data_type);
1394 }
1395
1396 /*
1397 * Returns the adler-32 checksum.
1398 */
1399 static VALUE
1400 rb_zstream_adler(VALUE obj)
1401 {
1402 return rb_uint2inum(get_zstream(obj)->stream.adler);
1403 }
1404
1405 /*
1406 * Returns true if the stream is finished.
1407 */
1408 static VALUE
1409 rb_zstream_finished_p(VALUE obj)
1410 {
1411 return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
1412 }
1413
1414 /*
1415 * Returns true if the stream is closed.
1416 */
1417 static VALUE
1418 rb_zstream_closed_p(VALUE obj)
1419 {
1420 struct zstream *z;
1421 Data_Get_Struct(obj, struct zstream, z);
1422 return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
1423 }
1424
1425
1426 /* ------------------------------------------------------------------------- */
1427
1428 /*
1429 * Document-class: Zlib::Deflate
1430 *
1431 * Zlib::Deflate is the class for compressing data. See Zlib::ZStream for more
1432 * information.
1433 */
1434
1435 #define FIXNUMARG(val, ifnil) \
1436 (NIL_P((val)) ? (ifnil) \
1437 : ((void)Check_Type((val), T_FIXNUM), FIX2INT((val))))
1438
1439 #define ARG_LEVEL(val) FIXNUMARG((val), Z_DEFAULT_COMPRESSION)
1440 #define ARG_WBITS(val) FIXNUMARG((val), MAX_WBITS)
1441 #define ARG_MEMLEVEL(val) FIXNUMARG((val), DEF_MEM_LEVEL)
1442 #define ARG_STRATEGY(val) FIXNUMARG((val), Z_DEFAULT_STRATEGY)
1443 #define ARG_FLUSH(val) FIXNUMARG((val), Z_NO_FLUSH)
1444
1445
1446 static VALUE
1447 rb_deflate_s_allocate(VALUE klass)
1448 {
1449 return zstream_deflate_new(klass);
1450 }
1451
1452 /*
1453 * Document-method: Zlib::Deflate.new
1454 *
1455 * call-seq:
1456 * Zlib::Deflate.new(level=DEFAULT_COMPRESSION, window_bits=MAX_WBITS, mem_level=DEF_MEM_LEVEL, strategy=DEFAULT_STRATEGY)
1457 *
1458 * Creates a new deflate stream for compression. If a given argument is nil,
1459 * the default value of that argument is used.
1460 *
1461 * The +level+ sets the compression level for the deflate stream between 0 (no
1462 * compression) and 9 (best compression. The following constants have been
1463 * defined to make code more readable:
1464 *
1465 * * Zlib::NO_COMPRESSION = 0
1466 * * Zlib::BEST_SPEED = 1
1467 * * Zlib::DEFAULT_COMPRESSION = 6
1468 * * Zlib::BEST_COMPRESSION = 9
1469 *
1470 * The +window_bits+ sets the size of the history buffer and should be between
1471 * 8 and 15. Larger values of this parameter result in better compression at
1472 * the expense of memory usage.
1473 *
1474 * The +mem_level+ specifies how much memory should be allocated for the
1475 * internal compression state. 1 uses minimum memory but is slow and reduces
1476 * compression ratio while 9 uses maximum memory for optimal speed. The
1477 * default value is 8. Two constants are defined:
1478 *
1479 * * Zlib::DEF_MEM_LEVEL
1480 * * Zlib::MAX_MEM_LEVEL
1481 *
1482 * The +strategy+ sets the deflate compression strategy. The following
1483 * strategies are available:
1484 *
1485 * Zlib::DEFAULT_STRATEGY:: For normal data
1486 * Zlib::FILTERED:: For data produced by a filter or predictor
1487 * Zlib::FIXED:: Prevents dynamic Huffman codes
1488 * Zlib::HUFFMAN_ONLY:: Prevents string matching
1489 * Zlib::RLE:: Designed for better compression of PNG image data
1490 *
1491 * See the constants for further description.
1492 *
1493 * == Examples
1494 *
1495 * === Basic
1496 *
1497 * open "compressed.file", "w+" do |io|
1498 * io << Zlib::Deflate.new.deflate(File.read("big.file"))
1499 * end
1500 *
1501 * === Custom compression
1502 *
1503 * open "compressed.file", "w+" do |compressed_io|
1504 * deflate = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
1505 * Zlib::MAX_WBITS,
1506 * Zlib::MAX_MEM_LEVEL,
1507 * Zlib::HUFFMAN_ONLY)
1508 *
1509 * begin
1510 * open "big.file" do |big_io|
1511 * until big_io.eof? do
1512 * compressed_io << zd.deflate(big_io.read(16384))
1513 * end
1514 * end
1515 * ensure
1516 * deflate.close
1517 * end
1518 * end
1519 *
1520 * While this example will work, for best optimization review the flags for
1521 * your specific time, memory usage and output space requirements.
1522 */
1523 static VALUE
1524 rb_deflate_initialize(int argc, VALUE *argv, VALUE obj)
1525 {
1526 struct zstream *z;
1527 VALUE level, wbits, memlevel, strategy;
1528 int err;
1529
1530 rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
1531 Data_Get_Struct(obj, struct zstream, z);
1532
1533 err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
1534 ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
1535 ARG_STRATEGY(strategy));
1536 if (err != Z_OK) {
1537 raise_zlib_error(err, z->stream.msg);
1538 }
1539 ZSTREAM_READY(z);
1540
1541 return obj;
1542 }
1543
1544 /*
1545 * Document-method: Zlib::Deflate#initialize_copy
1546 *
1547 * Duplicates the deflate stream.
1548 */
1549 static VALUE
1550 rb_deflate_init_copy(VALUE self, VALUE orig)
1551 {
1552 struct zstream *z1, *z2;
1553 int err;
1554
1555 Data_Get_Struct(self, struct zstream, z1);
1556 z2 = get_zstream(orig);
1557
1558 err = deflateCopy(&z1->stream, &z2->stream);
1559 if (err != Z_OK) {
1560 raise_zlib_error(err, 0);
1561 }
1562 z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
1563 z1->buf = NIL_P(z2->buf) ? Qnil : rb_str_dup(z2->buf);
1564 z1->buf_filled = z2->buf_filled;
1565 z1->flags = z2->flags;
1566
1567 return self;
1568 }
1569
1570 static VALUE
1571 deflate_run(VALUE args)
1572 {
1573 struct zstream *z = (struct zstream*)((VALUE*)args)[0];
1574 VALUE src = ((VALUE*)args)[1];
1575
1576 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_FINISH);
1577 return zstream_detach_buffer(z);
1578 }
1579
1580 /*
1581 * Document-method: Zlib::Deflate.deflate
1582 *
1583 * call-seq:
1584 * Zlib.deflate(string[, level])
1585 * Zlib::Deflate.deflate(string[, level])
1586 *
1587 * Compresses the given +string+. Valid values of level are
1588 * Zlib::NO_COMPRESSION, Zlib::BEST_SPEED, Zlib::BEST_COMPRESSION,
1589 * Zlib::DEFAULT_COMPRESSION, or an integer from 0 to 9 (the default is 6).
1590 *
1591 * This method is almost equivalent to the following code:
1592 *
1593 * def deflate(string, level)
1594 * z = Zlib::Deflate.new(level)
1595 * dst = z.deflate(string, Zlib::FINISH)
1596 * z.close
1597 * dst
1598 * end
1599 *
1600 * See also Zlib.inflate
1601 *
1602 */
1603 static VALUE
1604 rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass)
1605 {
1606 struct zstream z;
1607 VALUE src, level, dst, args[2];
1608 int err, lev;
1609
1610 rb_scan_args(argc, argv, "11", &src, &level);
1611
1612 lev = ARG_LEVEL(level);
1613 StringValue(src);
1614 zstream_init_deflate(&z);
1615 err = deflateInit(&z.stream, lev);
1616 if (err != Z_OK) {
1617 raise_zlib_error(err, z.stream.msg);
1618 }
1619 ZSTREAM_READY(&z);
1620
1621 args[0] = (VALUE)&z;
1622 args[1] = src;
1623 dst = rb_ensure(deflate_run, (VALUE)args, zstream_end, (VALUE)&z);
1624
1625 OBJ_INFECT(dst, src);
1626 return dst;
1627 }
1628
1629 static void
1630 do_deflate(struct zstream *z, VALUE src, int flush)
1631 {
1632 if (NIL_P(src)) {
1633 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1634 return;
1635 }
1636 StringValue(src);
1637 if (flush != Z_NO_FLUSH || RSTRING_LEN(src) > 0) { /* prevent BUF_ERROR */
1638 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), flush);
1639 }
1640 }
1641
1642 /*
1643 * Document-method: Zlib::Deflate#deflate
1644 *
1645 * call-seq:
1646 * z.deflate(string, flush = Zlib::NO_FLUSH) -> String
1647 * z.deflate(string, flush = Zlib::NO_FLUSH) { |chunk| ... } -> nil
1648 *
1649 * Inputs +string+ into the deflate stream and returns the output from the
1650 * stream. On calling this method, both the input and the output buffers of
1651 * the stream are flushed. If +string+ is nil, this method finishes the
1652 * stream, just like Zlib::ZStream#finish.
1653 *
1654 * If a block is given consecutive deflated chunks from the +string+ are
1655 * yielded to the block and +nil+ is returned.
1656 *
1657 * The +flush+ parameter specifies the flush mode. The following constants
1658 * may be used:
1659 *
1660 * Zlib::NO_FLUSH:: The default
1661 * Zlib::SYNC_FLUSH:: Flushes the output to a byte boundary
1662 * Zlib::FULL_FLUSH:: SYNC_FLUSH + resets the compression state
1663 * Zlib::FINISH:: Pending input is processed, pending output is flushed.
1664 *
1665 * See the constants for further description.
1666 *
1667 */
1668 static VALUE
1669 rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
1670 {
1671 struct zstream *z = get_zstream(obj);
1672 VALUE src, flush;
1673
1674 rb_scan_args(argc, argv, "11", &src, &flush);
1675 OBJ_INFECT(obj, src);
1676 do_deflate(z, src, ARG_FLUSH(flush));
1677
1678 return zstream_detach_buffer(z);
1679 }
1680
1681 /*
1682 * Document-method: Zlib::Deflate#<<
1683 *
1684 * call-seq: << string
1685 *
1686 * Inputs +string+ into the deflate stream just like Zlib::Deflate#deflate, but
1687 * returns the Zlib::Deflate object itself. The output from the stream is
1688 * preserved in output buffer.
1689 */
1690 static VALUE
1691 rb_deflate_addstr(VALUE obj, VALUE src)
1692 {
1693 OBJ_INFECT(obj, src);
1694 do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
1695 return obj;
1696 }
1697
1698 /*
1699 * Document-method: Zlib::Deflate#flush
1700 *
1701 * call-seq:
1702 * flush(flush = Zlib::SYNC_FLUSH) -> String
1703 * flush(flush = Zlib::SYNC_FLUSH) { |chunk| ... } -> nil
1704 *
1705 * This method is equivalent to <tt>deflate('', flush)</tt>. This method is
1706 * just provided to improve the readability of your Ruby program. If a block
1707 * is given chunks of deflate output are yielded to the block until the buffer
1708 * is flushed.
1709 *
1710 * See Zlib::Deflate#deflate for detail on the +flush+ constants NO_FLUSH,
1711 * SYNC_FLUSH, FULL_FLUSH and FINISH.
1712 */
1713 static VALUE
1714 rb_deflate_flush(int argc, VALUE *argv, VALUE obj)
1715 {
1716 struct zstream *z = get_zstream(obj);
1717 VALUE v_flush;
1718 int flush;
1719
1720 rb_scan_args(argc, argv, "01", &v_flush);
1721 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
1722 if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
1723 zstream_run(z, (Bytef*)"", 0, flush);
1724 }
1725
1726 return zstream_detach_buffer(z);
1727 }
1728
1729 /*
1730 * Document-method: Zlib::Deflate.params
1731 *
1732 * call-seq: params(level, strategy)
1733 *
1734 * Changes the parameters of the deflate stream to allow changes between
1735 * different types of data that require different types of compression. Any
1736 * unprocessed data is flushed before changing the params.
1737 *
1738 * See Zlib::Deflate.new for a description of +level+ and +strategy+.
1739 *
1740 */
1741 static VALUE
1742 rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy)
1743 {
1744 struct zstream *z = get_zstream(obj);
1745 int level, strategy;
1746 int err;
1747 uInt n;
1748
1749 level = ARG_LEVEL(v_level);
1750 strategy = ARG_STRATEGY(v_strategy);
1751
1752 n = z->stream.avail_out;
1753 err = deflateParams(&z->stream, level, strategy);
1754 z->buf_filled += n - z->stream.avail_out;
1755 while (err == Z_BUF_ERROR) {
1756 rb_warning("deflateParams() returned Z_BUF_ERROR");
1757 zstream_expand_buffer(z);
1758 n = z->stream.avail_out;
1759 err = deflateParams(&z->stream, level, strategy);
1760 z->buf_filled += n - z->stream.avail_out;
1761 }
1762 if (err != Z_OK) {
1763 raise_zlib_error(err, z->stream.msg);
1764 }
1765
1766 return Qnil;
1767 }
1768
1769 /*
1770 * Document-method: Zlib::Deflate.set_dictionary
1771 *
1772 * call-seq: set_dictionary(string)
1773 *
1774 * Sets the preset dictionary and returns +string+. This method is available
1775 * just only after Zlib::Deflate.new or Zlib::ZStream#reset method was called.
1776 * See zlib.h for details.
1777 *
1778 * Can raise errors of Z_STREAM_ERROR if a parameter is invalid (such as
1779 * NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if
1780 * the given dictionary doesn't match the expected one (incorrect adler32 value)
1781 *
1782 */
1783 static VALUE
1784 rb_deflate_set_dictionary(VALUE obj, VALUE dic)
1785 {
1786 struct zstream *z = get_zstream(obj);
1787 VALUE src = dic;
1788 int err;
1789
1790 OBJ_INFECT(obj, dic);
1791 StringValue(src);
1792 err = deflateSetDictionary(&z->stream,
1793 (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
1794 if (err != Z_OK) {
1795 raise_zlib_error(err, z->stream.msg);
1796 }
1797
1798 return dic;
1799 }
1800
1801
1802 /* ------------------------------------------------------------------------- */
1803
1804 /*
1805 * Document-class: Zlib::Inflate
1806 *
1807 * Zlib:Inflate is the class for decompressing compressed data. Unlike
1808 * Zlib::Deflate, an instance of this class is not able to duplicate (clone,
1809 * dup) itself.
1810 */
1811
1812 static VALUE
1813 rb_inflate_s_allocate(VALUE klass)
1814 {
1815 VALUE inflate = zstream_inflate_new(klass);
1816 rb_ivar_set(inflate, id_dictionaries, rb_hash_new());
1817 return inflate;
1818 }
1819
1820 /*
1821 * Document-method: Zlib::Inflate.new
1822 *
1823 * call-seq:
1824 * Zlib::Inflate.new(window_bits = Zlib::MAX_WBITS)
1825 *
1826 * Creates a new inflate stream for decompression. +window_bits+ sets the
1827 * size of the history buffer and can have the following values:
1828 *
1829 * 0::
1830 * Have inflate use the window size from the zlib header of the compressed
1831 * stream.
1832 *
1833 * (8..15)
1834 * Overrides the window size of the inflate header in the compressed stream.
1835 * The window size must be greater than or equal to the window size of the
1836 * compressed stream.
1837 *
1838 * Greater than 15::
1839 * Add 32 to window_bits to enable zlib and gzip decoding with automatic
1840 * header detection, or add 16 to decode only the gzip format (a
1841 * Zlib::DataError will be raised for a non-gzip stream).
1842 *
1843 * (-8..-15)::
1844 * Enables raw deflate mode which will not generate a check value, and will
1845 * not look for any check values for comparison at the end of the stream.
1846 *
1847 * This is for use with other formats that use the deflate compressed data
1848 * format such as zip which provide their own check values.
1849 *
1850 * == Example
1851 *
1852 * open "compressed.file" do |compressed_io|
1853 * inflate = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
1854 *
1855 * begin
1856 * open "uncompressed.file", "w+" do |uncompressed_io|
1857 * uncompressed_io << zi.inflate(compressed_io.read)
1858 * }
1859 * ensure
1860 * zi.close
1861 * end
1862 * end
1863 *
1864 */
1865 static VALUE
1866 rb_inflate_initialize(int argc, VALUE *argv, VALUE obj)
1867 {
1868 struct zstream *z;
1869 VALUE wbits;
1870 int err;
1871
1872 rb_scan_args(argc, argv, "01", &wbits);
1873 Data_Get_Struct(obj, struct zstream, z);
1874
1875 err = inflateInit2(&z->stream, ARG_WBITS(wbits));
1876 if (err != Z_OK) {
1877 raise_zlib_error(err, z->stream.msg);
1878 }
1879 ZSTREAM_READY(z);
1880
1881 return obj;
1882 }
1883
1884 static VALUE
1885 inflate_run(VALUE args)
1886 {
1887 struct zstream *z = (struct zstream*)((VALUE*)args)[0];
1888 VALUE src = ((VALUE*)args)[1];
1889
1890 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
1891 zstream_run(z, (Bytef*)"", 0, Z_FINISH); /* for checking errors */
1892 return zstream_detach_buffer(z);
1893 }
1894
1895 /*
1896 * Document-method: Zlib::inflate
1897 *
1898 * call-seq:
1899 * Zlib.inflate(string)
1900 * Zlib::Inflate.inflate(string)
1901 *
1902 * Decompresses +string+. Raises a Zlib::NeedDict exception if a preset
1903 * dictionary is needed for decompression.
1904 *
1905 * This method is almost equivalent to the following code:
1906 *
1907 * def inflate(string)
1908 * zstream = Zlib::Inflate.new
1909 * buf = zstream.inflate(string)
1910 * zstream.finish
1911 * zstream.close
1912 * buf
1913 * end
1914 *
1915 * See also Zlib.deflate
1916 *
1917 */
1918 static VALUE
1919 rb_inflate_s_inflate(VALUE obj, VALUE src)
1920 {
1921 struct zstream z;
1922 VALUE dst, args[2];
1923 int err;
1924
1925 StringValue(src);
1926 zstream_init_inflate(&z);
1927 err = inflateInit(&z.stream);
1928 if (err != Z_OK) {
1929 raise_zlib_error(err, z.stream.msg);
1930 }
1931 ZSTREAM_READY(&z);
1932
1933 args[0] = (VALUE)&z;
1934 args[1] = src;
1935 dst = rb_ensure(inflate_run, (VALUE)args, zstream_end, (VALUE)&z);
1936
1937 OBJ_INFECT(dst, src);
1938 return dst;
1939 }
1940
1941 static void
1942 do_inflate(struct zstream *z, VALUE src)
1943 {
1944 if (NIL_P(src)) {
1945 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1946 return;
1947 }
1948 StringValue(src);
1949 if (RSTRING_LEN(src) > 0 || z->stream.avail_in > 0) { /* prevent Z_BUF_ERROR */
1950 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
1951 }
1952 }
1953
1954 /* Document-method: Zlib::Inflate#add_dictionary
1955 *
1956 * call-seq: add_dictionary(string)
1957 *
1958 * Provide the inflate stream with a dictionary that may be required in the
1959 * future. Multiple dictionaries may be provided. The inflate stream will
1960 * automatically choose the correct user-provided dictionary based on the
1961 * stream's required dictionary.
1962 */
1963 static VALUE
1964 rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) {
1965 VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
1966 VALUE checksum = do_checksum(1, &dictionary, adler32);
1967
1968 rb_hash_aset(dictionaries, checksum, dictionary);
1969
1970 return obj;
1971 }
1972
1973 /*
1974 * Document-method: Zlib::Inflate#inflate
1975 *
1976 * call-seq:
1977 * inflate(deflate_string) -> String
1978 * inflate(deflate_string) { |chunk| ... } -> nil
1979 *
1980 * Inputs +deflate_string+ into the inflate stream and returns the output from
1981 * the stream. Calling this method, both the input and the output buffer of
1982 * the stream are flushed. If string is +nil+, this method finishes the
1983 * stream, just like Zlib::ZStream#finish.
1984 *
1985 * If a block is given consecutive inflated chunks from the +deflate_string+
1986 * are yielded to the block and +nil+ is returned.
1987 *
1988 * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
1989 * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
1990 * call this method again with an empty string to flush the stream:
1991 *
1992 * inflater = Zlib::Inflate.new
1993 *
1994 * begin
1995 * out = inflater.inflate compressed
1996 * rescue Zlib::NeedDict
1997 * # ensure the dictionary matches the stream's required dictionary
1998 * raise unless inflater.adler == Zlib.adler32(dictionary)
1999 *
2000 * inflater.set_dictionary dictionary
2001 * inflater.inflate ''
2002 * end
2003 *
2004 * # ...
2005 *
2006 * inflater.close
2007 *
2008 * See also Zlib::Inflate.new
2009 */
2010 static VALUE
2011 rb_inflate_inflate(VALUE obj, VALUE src)
2012 {
2013 struct zstream *z = get_zstream(obj);
2014 VALUE dst;
2015
2016 OBJ_INFECT(obj, src);
2017
2018 if (ZSTREAM_IS_FINISHED(z)) {
2019 if (NIL_P(src)) {
2020 dst = zstream_detach_buffer(z);
2021 }
2022 else {
2023 StringValue(src);
2024 zstream_append_buffer2(z, src);
2025 dst = rb_str_new(0, 0);
2026 OBJ_INFECT(dst, obj);
2027 }
2028 }
2029 else {
2030 do_inflate(z, src);
2031 dst = zstream_detach_buffer(z);
2032 if (ZSTREAM_IS_FINISHED(z)) {
2033 zstream_passthrough_input(z);
2034 }
2035 }
2036
2037 return dst;
2038 }
2039
2040 /*
2041 * call-seq: << string
2042 *
2043 * Inputs +string+ into the inflate stream just like Zlib::Inflate#inflate, but
2044 * returns the Zlib::Inflate object itself. The output from the stream is
2045 * preserved in output buffer.
2046 */
2047 static VALUE
2048 rb_inflate_addstr(VALUE obj, VALUE src)
2049 {
2050 struct zstream *z = get_zstream(obj);
2051
2052 OBJ_INFECT(obj, src);
2053
2054 if (ZSTREAM_IS_FINISHED(z)) {
2055 if (!NIL_P(src)) {
2056 StringValue(src);
2057 zstream_append_buffer2(z, src);
2058 }
2059 }
2060 else {
2061 do_inflate(z, src);
2062 if (ZSTREAM_IS_FINISHED(z)) {
2063 zstream_passthrough_input(z);
2064 }
2065 }
2066
2067 return obj;
2068 }
2069
2070 /*
2071 * call-seq: sync(string)
2072 *
2073 * Inputs +string+ into the end of input buffer and skips data until a full
2074 * flush point can be found. If the point is found in the buffer, this method
2075 * flushes the buffer and returns false. Otherwise it returns +true+ and the
2076 * following data of full flush point is preserved in the buffer.
2077 */
2078 static VALUE
2079 rb_inflate_sync(VALUE obj, VALUE src)
2080 {
2081 struct zstream *z = get_zstream(obj);
2082
2083 OBJ_INFECT(obj, src);
2084 StringValue(src);
2085 return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
2086 }
2087
2088 /*
2089 * Quoted verbatim from original documentation:
2090 *
2091 * What is this?
2092 *
2093 * <tt>:)</tt>
2094 */
2095 static VALUE
2096 rb_inflate_sync_point_p(VALUE obj)
2097 {
2098 struct zstream *z = get_zstream(obj);
2099 int err;
2100
2101 err = inflateSyncPoint(&z->stream);
2102 if (err == 1) {
2103 return Qtrue;
2104 }
2105 if (err != Z_OK) {
2106 raise_zlib_error(err, z->stream.msg);
2107 }
2108 return Qfalse;
2109 }
2110
2111 /*
2112 * Document-method: Zlib::Inflate#set_dictionary
2113 *
2114 * Sets the preset dictionary and returns +string+. This method is available just
2115 * only after a Zlib::NeedDict exception was raised. See zlib.h for details.
2116 *
2117 */
2118 static VALUE
2119 rb_inflate_set_dictionary(VALUE obj, VALUE dic)
2120 {
2121 struct zstream *z = get_zstream(obj);
2122 VALUE src = dic;
2123 int err;
2124
2125 OBJ_INFECT(obj, dic);
2126 StringValue(src);
2127 err = inflateSetDictionary(&z->stream,
2128 (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
2129 if (err != Z_OK) {
2130 raise_zlib_error(err, z->stream.msg);
2131 }
2132
2133 return dic;
2134 }
2135
2136
2137
2138 #if GZIP_SUPPORT
2139
2140 /* NOTE: Features for gzip files of Ruby/zlib are written from scratch
2141 * and using undocumented feature of zlib, negative wbits.
2142 * I don't think gzFile APIs of zlib are good for Ruby.
2143 */
2144
2145 /*------- .gz file header --------*/
2146
2147 #define GZ_MAGIC1 0x1f
2148 #define GZ_MAGIC2 0x8b
2149 #define GZ_METHOD_DEFLATE 8
2150 #define GZ_FLAG_MULTIPART 0x2
2151 #define GZ_FLAG_EXTRA 0x4
2152 #define GZ_FLAG_ORIG_NAME 0x8
2153 #define GZ_FLAG_COMMENT 0x10
2154 #define GZ_FLAG_ENCRYPT 0x20
2155 #define GZ_FLAG_UNKNOWN_MASK 0xc0
2156
2157 #define GZ_EXTRAFLAG_FAST 0x4
2158 #define GZ_EXTRAFLAG_SLOW 0x2
2159
2160 /* from zutil.h */
2161 #define OS_MSDOS 0x00
2162 #define OS_AMIGA 0x01
2163 #define OS_VMS 0x02
2164 #define OS_UNIX 0x03
2165 #define OS_ATARI 0x05
2166 #define OS_OS2 0x06
2167 #define OS_MACOS 0x07
2168 #define OS_TOPS20 0x0a
2169 #define OS_WIN32 0x0b
2170
2171 #define OS_VMCMS 0x04
2172 #define OS_ZSYSTEM 0x08
2173 #define OS_CPM 0x09
2174 #define OS_QDOS 0x0c
2175 #define OS_RISCOS 0x0d
2176 #define OS_UNKNOWN 0xff
2177
2178 #ifndef OS_CODE
2179 #define OS_CODE OS_UNIX
2180 #endif
2181
2182 static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
2183 static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
2184
2185
2186
2187 /*-------- gzfile internal APIs --------*/
2188
2189 struct gzfile {
2190 struct zstream z;
2191 VALUE io;
2192 int level;
2193 time_t mtime; /* for header */
2194 int os_code; /* for header */
2195 VALUE orig_name; /* for header; must be a String */
2196 VALUE comment; /* for header; must be a String */
2197 unsigned long crc;
2198 int lineno;
2199 long ungetc;
2200 void (*end)(struct gzfile *);
2201 rb_encoding *enc;
2202 rb_encoding *enc2;
2203 rb_econv_t *ec;
2204 int ecflags;
2205 VALUE ecopts;
2206 char *cbuf;
2207 VALUE path;
2208 };
2209 #define GZFILE_CBUF_CAPA 10
2210
2211 #define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
2212 #define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
2213 #define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2)
2214
2215 #define GZFILE_IS_FINISHED(gz) \
2216 (ZSTREAM_IS_FINISHED(&(gz)->z) && (gz)->z.buf_filled == 0)
2217
2218 #define GZFILE_READ_SIZE 2048
2219
2220
2221 static void
2222 gzfile_mark(struct gzfile *gz)
2223 {
2224 rb_gc_mark(gz->io);
2225 rb_gc_mark(gz->orig_name);
2226 rb_gc_mark(gz->comment);
2227 zstream_mark(&gz->z);
2228 rb_gc_mark(gz->ecopts);
2229 rb_gc_mark(gz->path);
2230 }
2231
2232 static void
2233 gzfile_free(struct gzfile *gz)
2234 {
2235 struct zstream *z = &gz->z;
2236
2237 if (ZSTREAM_IS_READY(z)) {
2238 if (z->func == &deflate_funcs) {
2239 finalizer_warn("Zlib::GzipWriter object must be closed explicitly.");
2240 }
2241 zstream_finalize(z);
2242 }
2243 if (gz->cbuf) {
2244 xfree(gz->cbuf);
2245 }
2246 xfree(gz);
2247 }
2248
2249 static VALUE
2250 gzfile_new(klass, funcs, endfunc)
2251 VALUE klass;
2252 const struct zstream_funcs *funcs;
2253 void (*endfunc)(struct gzfile *);
2254 {
2255 VALUE obj;
2256 struct gzfile *gz;
2257
2258 obj = Data_Make_Struct(klass, struct gzfile, gzfile_mark, gzfile_free, gz);
2259 zstream_init(&gz->z, funcs);
2260 gz->z.flags |= ZSTREAM_FLAG_GZFILE;
2261 gz->io = Qnil;
2262 gz->level = 0;
2263 gz->mtime = 0;
2264 gz->os_code = OS_CODE;
2265 gz->orig_name = Qnil;
2266 gz->comment = Qnil;
2267 gz->crc = crc32(0, Z_NULL, 0);
2268 gz->lineno = 0;
2269 gz->ungetc = 0;
2270 gz->end = endfunc;
2271 gz->enc = rb_default_external_encoding();
2272 gz->enc2 = 0;
2273 gz->ec = NULL;
2274 gz->ecflags = 0;
2275 gz->ecopts = Qnil;
2276 gz->cbuf = 0;
2277 gz->path = Qnil;
2278
2279 return obj;
2280 }
2281
2282 #define gzfile_writer_new(gz) gzfile_new((gz),&deflate_funcs,gzfile_writer_end)
2283 #define gzfile_reader_new(gz) gzfile_new((gz),&inflate_funcs,gzfile_reader_end)
2284
2285 static void
2286 gzfile_reset(struct gzfile *gz)
2287 {
2288 zstream_reset(&gz->z);
2289 gz->crc = crc32(0, Z_NULL, 0);
2290 gz->lineno = 0;
2291 gz->ungetc = 0;
2292 if (gz->ec) {
2293 rb_econv_close(gz->ec);
2294 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
2295 gz->ecflags, gz->ecopts);
2296 }
2297 }
2298
2299 static void
2300 gzfile_close(struct gzfile *gz, int closeflag)
2301 {
2302 VALUE io = gz->io;
2303
2304 gz->end(gz);
2305 gz->io = Qnil;
2306 gz->orig_name = Qnil;
2307 gz->comment = Qnil;
2308 if (closeflag && rb_respond_to(io, id_close)) {
2309 rb_funcall(io, id_close, 0);
2310 }
2311 }
2312
2313 static void
2314 gzfile_write_raw(struct gzfile *gz)
2315 {
2316 VALUE str;
2317
2318 if (gz->z.buf_filled > 0) {
2319 str = zstream_detach_buffer(&gz->z);
2320 OBJ_TAINT(str); /* for safe */
2321 rb_funcall(gz->io, id_write, 1, str);
2322 if ((gz->z.flags & GZFILE_FLAG_SYNC)
2323 && rb_respond_to(gz->io, id_flush))
2324 rb_funcall(gz->io, id_flush, 0);
2325 }
2326 }
2327
2328 static VALUE
2329 gzfile_read_raw_partial(VALUE arg)
2330 {
2331 struct gzfile *gz = (struct gzfile*)arg;
2332 VALUE str;
2333
2334 str = rb_funcall(gz->io, id_readpartial, 1, INT2FIX(GZFILE_READ_SIZE));
2335 Check_Type(str, T_STRING);
2336 return str;
2337 }
2338
2339 static VALUE
2340 gzfile_read_raw_rescue(VALUE arg)
2341 {
2342 struct gzfile *gz = (struct gzfile*)arg;
2343 VALUE str = Qnil;
2344 if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
2345 str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
2346 if (!NIL_P(str)) {
2347 Check_Type(str, T_STRING);
2348 }
2349 }
2350 return str; /* return nil when EOFError */
2351 }
2352
2353 static VALUE
2354 gzfile_read_raw(struct gzfile *gz)
2355 {
2356 return rb_rescue2(gzfile_read_raw_partial, (VALUE)gz,
2357 gzfile_read_raw_rescue, (VALUE)gz,
2358 rb_eEOFError, rb_eNoMethodError, (VALUE)0);
2359 }
2360
2361 static int
2362 gzfile_read_raw_ensure(struct gzfile *gz, long size)
2363 {
2364 VALUE str;
2365
2366 while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
2367 str = gzfile_read_raw(gz);
2368 if (NIL_P(str)) return 0;
2369 zstream_append_input2(&gz->z, str);
2370 }
2371 return 1;
2372 }
2373
2374 static char *
2375 gzfile_read_raw_until_zero(struct gzfile *gz, long offset)
2376 {
2377 VALUE str;
2378 char *p;
2379
2380 for (;;) {
2381 p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
2382 RSTRING_LEN(gz->z.input) - offset);
2383 if (p) break;
2384 str = gzfile_read_raw(gz);
2385 if (NIL_P(str)) {
2386 rb_raise(cGzError, "unexpected end of file");
2387 }
2388 offset = RSTRING_LEN(gz->z.input);
2389 zstream_append_input2(&gz->z, str);
2390 }
2391 return p;
2392 }
2393
2394 static unsigned int
2395 gzfile_get16(const unsigned char *src)
2396 {
2397 unsigned int n;
2398 n = *(src++) & 0xff;
2399 n |= (*(src++) & 0xff) << 8;
2400 return n;
2401 }
2402
2403 static unsigned long
2404 gzfile_get32(const unsigned char *src)
2405 {
2406 unsigned long n;
2407 n = *(src++) & 0xff;
2408 n |= (*(src++) & 0xff) << 8;
2409 n |= (*(src++) & 0xff) << 16;
2410 n |= (*(src++) & 0xffU) << 24;
2411 return n;
2412 }
2413
2414 static void
2415 gzfile_set32(unsigned long n, unsigned char *dst)
2416 {
2417 *(dst++) = n & 0xff;
2418 *(dst++) = (n >> 8) & 0xff;
2419 *(dst++) = (n >> 16) & 0xff;
2420 *dst = (n >> 24) & 0xff;
2421 }
2422
2423 static void
2424 gzfile_raise(struct gzfile *gz, VALUE klass, const char *message)
2425 {
2426 VALUE exc = rb_exc_new2(klass, message);
2427 if (!NIL_P(gz->z.input)) {
2428 rb_ivar_set(exc, id_input, rb_str_resurrect(gz->z.input));
2429 }
2430 rb_exc_raise(exc);
2431 }
2432
2433 /*
2434 * Document-method: Zlib::GzipFile::Error#inspect
2435 *
2436 * Constructs a String of the GzipFile Error
2437 */
2438 static VALUE
2439 gzfile_error_inspect(VALUE error)
2440 {
2441 VALUE str = rb_call_super(0, 0);
2442 VALUE input = rb_attr_get(error, id_input);
2443
2444 if (!NIL_P(input)) {
2445 rb_str_resize(str, RSTRING_LEN(str)-1);
2446 rb_str_cat2(str, ", input=");
2447 rb_str_append(str, rb_str_inspect(input));
2448 rb_str_cat2(str, ">");
2449 }
2450 return str;
2451 }
2452
2453 static void
2454 gzfile_make_header(struct gzfile *gz)
2455 {
2456 Bytef buf[10]; /* the size of gzip header */
2457 unsigned char flags = 0, extraflags = 0;
2458
2459 if (!NIL_P(gz->orig_name)) {
2460 flags |= GZ_FLAG_ORIG_NAME;
2461 }
2462 if (!NIL_P(gz->comment)) {
2463 flags |= GZ_FLAG_COMMENT;
2464 }
2465 if (gz->mtime == 0) {
2466 gz->mtime = time(0);
2467 }
2468
2469 if (gz->level == Z_BEST_SPEED) {
2470 extraflags |= GZ_EXTRAFLAG_FAST;
2471 }
2472 else if (gz->level == Z_BEST_COMPRESSION) {
2473 extraflags |= GZ_EXTRAFLAG_SLOW;
2474 }
2475
2476 buf[0] = GZ_MAGIC1;
2477 buf[1] = GZ_MAGIC2;
2478 buf[2] = GZ_METHOD_DEFLATE;
2479 buf[3] = flags;
2480 gzfile_set32((unsigned long)gz->mtime, &buf[4]);
2481 buf[8] = extraflags;
2482 buf[9] = gz->os_code;
2483 zstream_append_buffer(&gz->z, buf, sizeof(buf));
2484
2485 if (!NIL_P(gz->orig_name)) {
2486 zstream_append_buffer2(&gz->z, gz->orig_name);
2487 zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
2488 }
2489 if (!NIL_P(gz->comment)) {
2490 zstream_append_buffer2(&gz->z, gz->comment);
2491 zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
2492 }
2493
2494 gz->z.flags |= GZFILE_FLAG_HEADER_FINISHED;
2495 }
2496
2497 static void
2498 gzfile_make_footer(struct gzfile *gz)
2499 {
2500 Bytef buf[8]; /* 8 is the size of gzip footer */
2501
2502 gzfile_set32(gz->crc, buf);
2503 gzfile_set32(gz->z.stream.total_in, &buf[4]);
2504 zstream_append_buffer(&gz->z, buf, sizeof(buf));
2505 gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
2506 }
2507
2508 static void
2509 gzfile_read_header(struct gzfile *gz)
2510 {
2511 const unsigned char *head;
2512 long len;
2513 char flags, *p;
2514
2515 if (!gzfile_read_raw_ensure(gz, 10)) { /* 10 is the size of gzip header */
2516 gzfile_raise(gz, cGzError, "not in gzip format");
2517 }
2518
2519 head = (unsigned char*)RSTRING_PTR(gz->z.input);
2520
2521 if (head[0] != GZ_MAGIC1 || head[1] != GZ_MAGIC2) {
2522 gzfile_raise(gz, cGzError, "not in gzip format");
2523 }
2524 if (head[2] != GZ_METHOD_DEFLATE) {
2525 rb_raise(cGzError, "unsupported compression method %d", head[2]);
2526 }
2527
2528 flags = head[3];
2529 if (flags & GZ_FLAG_MULTIPART) {
2530 rb_raise(cGzError, "multi-part gzip file is not supported");
2531 }
2532 else if (flags & GZ_FLAG_ENCRYPT) {
2533 rb_raise(cGzError, "encrypted gzip file is not supported");
2534 }
2535 else if (flags & GZ_FLAG_UNKNOWN_MASK) {
2536 rb_raise(cGzError, "unknown flags 0x%02x", flags);
2537 }
2538
2539 if (head[8] & GZ_EXTRAFLAG_FAST) {
2540 gz->level = Z_BEST_SPEED;
2541 }
2542 else if (head[8] & GZ_EXTRAFLAG_SLOW) {
2543 gz->level = Z_BEST_COMPRESSION;
2544 }
2545 else {
2546 gz->level = Z_DEFAULT_COMPRESSION;
2547 }
2548
2549 gz->mtime = gzfile_get32(&head[4]);
2550 gz->os_code = head[9];
2551 zstream_discard_input(&gz->z, 10);
2552
2553 if (flags & GZ_FLAG_EXTRA) {
2554 if (!gzfile_read_raw_ensure(gz, 2)) {
2555 rb_raise(cGzError, "unexpected end of file");
2556 }
2557 len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
2558 if (!gzfile_read_raw_ensure(gz, 2 + len)) {
2559 rb_raise(cGzError, "unexpected end of file");
2560 }
2561 zstream_discard_input(&gz->z, 2 + len);
2562 }
2563 if (flags & GZ_FLAG_ORIG_NAME) {
2564 if (!gzfile_read_raw_ensure(gz, 1)) {
2565 rb_raise(cGzError, "unexpected end of file");
2566 }
2567 p = gzfile_read_raw_until_zero(gz, 0);
2568 len = p - RSTRING_PTR(gz->z.input);
2569 gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len);
2570 OBJ_TAINT(gz->orig_name); /* for safe */
2571 zstream_discard_input(&gz->z, len + 1);
2572 }
2573 if (flags & GZ_FLAG_COMMENT) {
2574 if (!gzfile_read_raw_ensure(gz, 1)) {
2575 rb_raise(cGzError, "unexpected end of file");
2576 }
2577 p = gzfile_read_raw_until_zero(gz, 0);
2578 len = p - RSTRING_PTR(gz->z.input);
2579 gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
2580 OBJ_TAINT(gz->comment); /* for safe */
2581 zstream_discard_input(&gz->z, len + 1);
2582 }
2583
2584 if (gz->z.input != Qnil && RSTRING_LEN(gz->z.input) > 0) {
2585 zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH);
2586 }
2587 }
2588
2589 static void
2590 gzfile_check_footer(struct gzfile *gz)
2591 {
2592 unsigned long crc, length;
2593
2594 gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
2595
2596 if (!gzfile_read_raw_ensure(gz, 8)) { /* 8 is the size of gzip footer */
2597 gzfile_raise(gz, cNoFooter, "footer is not found");
2598 }
2599
2600 crc = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input));
2601 length = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input) + 4);
2602
2603 gz->z.stream.total_in += 8; /* to rewind correctly */
2604 zstream_discard_input(&gz->z, 8);
2605
2606 if (gz->crc != crc) {
2607 rb_raise(cCRCError, "invalid compressed data -- crc error");
2608 }
2609 if ((uint32_t)gz->z.stream.total_out != length) {
2610 rb_raise(cLengthError, "invalid compressed data -- length error");
2611 }
2612 }
2613
2614 static void
2615 gzfile_write(struct gzfile *gz, Bytef *str, long len)
2616 {
2617 if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2618 gzfile_make_header(gz);
2619 }
2620
2621 if (len > 0 || (gz->z.flags & GZFILE_FLAG_SYNC)) {
2622 gz->crc = checksum_long(crc32, gz->crc, str, len);
2623 zstream_run(&gz->z, str, len, (gz->z.flags & GZFILE_FLAG_SYNC)
2624 ? Z_SYNC_FLUSH : Z_NO_FLUSH);
2625 }
2626 gzfile_write_raw(gz);
2627 }
2628
2629 static long
2630 gzfile_read_more(struct gzfile *gz)
2631 {
2632 volatile VALUE str;
2633
2634 while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2635 str = gzfile_read_raw(gz);
2636 if (NIL_P(str)) {
2637 if (!ZSTREAM_IS_FINISHED(&gz->z)) {
2638 rb_raise(cGzError, "unexpected end of file");
2639 }
2640 break;
2641 }
2642 if (RSTRING_LEN(str) > 0) { /* prevent Z_BUF_ERROR */
2643 zstream_run(&gz->z, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str),
2644 Z_SYNC_FLUSH);
2645 }
2646 if (gz->z.buf_filled > 0) break;
2647 }
2648 return gz->z.buf_filled;
2649 }
2650
2651 static void
2652 gzfile_calc_crc(struct gzfile *gz, VALUE str)
2653 {
2654 if (RSTRING_LEN(str) <= gz->ungetc) {
2655 gz->ungetc -= RSTRING_LEN(str);
2656 }
2657 else {
2658 gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
2659 RSTRING_LEN(str) - gz->ungetc);
2660 gz->ungetc = 0;
2661 }
2662 }
2663
2664 static VALUE
2665 gzfile_newstr(struct gzfile *gz, VALUE str)
2666 {
2667 if (!gz->enc2) {
2668 rb_enc_associate(str, gz->enc);
2669 OBJ_TAINT(str); /* for safe */
2670 return str;
2671 }
2672 if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2673 str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
2674 rb_enc_associate(str, gz->enc);
2675 OBJ_TAINT(str);
2676 return str;
2677 }
2678 return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
2679 gz->ecflags, gz->ecopts);
2680 }
2681
2682 static long
2683 gzfile_fill(struct gzfile *gz, long len)
2684 {
2685 if (len < 0)
2686 rb_raise(rb_eArgError, "negative length %ld given", len);
2687 if (len == 0)
2688 return 0;
2689 while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
2690 gzfile_read_more(gz);
2691 }
2692 if (GZFILE_IS_FINISHED(gz)) {
2693 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2694 gzfile_check_footer(gz);
2695 }
2696 return -1;
2697 }
2698 return len < gz->z.buf_filled ? len : gz->z.buf_filled;
2699 }
2700
2701 static VALUE
2702 gzfile_read(struct gzfile *gz, long len)
2703 {
2704 VALUE dst;
2705
2706 len = gzfile_fill(gz, len);
2707 if (len == 0) return rb_str_new(0, 0);
2708 if (len < 0) return Qnil;
2709 dst = zstream_shift_buffer(&gz->z, len);
2710 if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
2711 return dst;
2712 }
2713
2714 static VALUE
2715 gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
2716 {
2717 VALUE dst;
2718
2719 if (len < 0)
2720 rb_raise(rb_eArgError, "negative length %ld given", len);
2721
2722 if (!NIL_P(outbuf))
2723 OBJ_TAINT(outbuf);
2724
2725 if (len == 0) {
2726 if (NIL_P(outbuf))
2727 return rb_str_new(0, 0);
2728 else {
2729 rb_str_resize(outbuf, 0);
2730 return outbuf;
2731 }
2732 }
2733 while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled == 0) {
2734 gzfile_read_more(gz);
2735 }
2736 if (GZFILE_IS_FINISHED(gz)) {
2737 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2738 gzfile_check_footer(gz);
2739 }
2740 if (!NIL_P(outbuf))
2741 rb_str_resize(outbuf, 0);
2742 rb_raise(rb_eEOFError, "end of file reached");
2743 }
2744
2745 dst = zstream_shift_buffer(&gz->z, len);
2746 gzfile_calc_crc(gz, dst);
2747
2748 if (!NIL_P(outbuf)) {
2749 rb_str_resize(outbuf, RSTRING_LEN(dst));
2750 memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
2751 dst = outbuf;
2752 }
2753 OBJ_TAINT(dst); /* for safe */
2754 return dst;
2755 }
2756
2757 static VALUE
2758 gzfile_read_all(struct gzfile *gz)
2759 {
2760 VALUE dst;
2761
2762 while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2763 gzfile_read_more(gz);
2764 }
2765 if (GZFILE_IS_FINISHED(gz)) {
2766 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2767 gzfile_check_footer(gz);
2768 }
2769 return rb_str_new(0, 0);
2770 }
2771
2772 dst = zstream_detach_buffer(&gz->z);
2773 if (NIL_P(dst)) return dst;
2774 gzfile_calc_crc(gz, dst);
2775 OBJ_TAINT(dst);
2776 return gzfile_newstr(gz, dst);
2777 }
2778
2779 static VALUE
2780 gzfile_getc(struct gzfile *gz)
2781 {
2782 VALUE buf, dst = 0;
2783 int len;
2784
2785 len = rb_enc_mbmaxlen(gz->enc);
2786 while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
2787 gzfile_read_more(gz);
2788 }
2789 if (GZFILE_IS_FINISHED(gz)) {
2790 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2791 gzfile_check_footer(gz);
2792 }
2793 return Qnil;
2794 }
2795
2796 if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2797 const unsigned char *ss, *sp, *se;
2798 unsigned char *ds, *dp, *de;
2799
2800 if (!gz->cbuf) {
2801 gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA);
2802 }
2803 ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
2804 se = sp + gz->z.buf_filled;
2805 ds = dp = (unsigned char *)gz->cbuf;
2806 de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
2807 (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
2808 rb_econv_check_error(gz->ec);
2809 dst = zstream_shift_buffer(&gz->z, sp - ss);
2810 gzfile_calc_crc(gz, dst);
2811 dst = rb_str_new(gz->cbuf, dp - ds);
2812 rb_enc_associate(dst, gz->enc);
2813 OBJ_TAINT(dst);
2814 return dst;
2815 }
2816 else {
2817 buf = gz->z.buf;
2818 len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
2819 dst = gzfile_read(gz, len);
2820 if (NIL_P(dst)) return dst;
2821 return gzfile_newstr(gz, dst);
2822 }
2823 }
2824
2825 static void
2826 gzfile_ungets(struct gzfile *gz, const Bytef *b, long len)
2827 {
2828 zstream_buffer_ungets(&gz->z, b, len);
2829 gz->ungetc+=len;
2830 }
2831
2832 static void
2833 gzfile_ungetbyte(struct gzfile *gz, int c)
2834 {
2835 zstream_buffer_ungetbyte(&gz->z, c);
2836 gz->ungetc++;
2837 }
2838
2839 static VALUE
2840 gzfile_writer_end_run(VALUE arg)
2841 {
2842 struct gzfile *gz = (struct gzfile *)arg;
2843
2844 if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2845 gzfile_make_header(gz);
2846 }
2847
2848 zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
2849 gzfile_make_footer(gz);
2850 gzfile_write_raw(gz);
2851
2852 return Qnil;
2853 }
2854
2855 static void
2856 gzfile_writer_end(struct gzfile *gz)
2857 {
2858 if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2859 gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2860
2861 rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
2862 }
2863
2864 static VALUE
2865 gzfile_reader_end_run(VALUE arg)
2866 {
2867 struct gzfile *gz = (struct gzfile *)arg;
2868
2869 if (GZFILE_IS_FINISHED(gz)
2870 && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2871 gzfile_check_footer(gz);
2872 }
2873
2874 return Qnil;
2875 }
2876
2877 static void
2878 gzfile_reader_end(struct gzfile *gz)
2879 {
2880 if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2881 gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2882
2883 rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
2884 }
2885
2886 static void
2887 gzfile_reader_rewind(struct gzfile *gz)
2888 {
2889 long n;
2890
2891 n = gz->z.stream.total_in;
2892 if (!NIL_P(gz->z.input)) {
2893 n += RSTRING_LEN(gz->z.input);
2894 }
2895
2896 rb_funcall(gz->io, id_seek, 2, rb_int2inum(-n), INT2FIX(1));
2897 gzfile_reset(gz);
2898 }
2899
2900 static VALUE
2901 gzfile_reader_get_unused(struct gzfile *gz)
2902 {
2903 VALUE str;
2904
2905 if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
2906 if (!GZFILE_IS_FINISHED(gz)) return Qnil;
2907 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2908 gzfile_check_footer(gz);
2909 }
2910 if (NIL_P(gz->z.input)) return Qnil;
2911
2912 str = rb_str_resurrect(gz->z.input);
2913 OBJ_TAINT(str); /* for safe */
2914 return str;
2915 }
2916
2917 static struct gzfile *
2918 get_gzfile(VALUE obj)
2919 {
2920 struct gzfile *gz;
2921
2922 Data_Get_Struct(obj, struct gzfile, gz);
2923 if (!ZSTREAM_IS_READY(&gz->z)) {
2924 rb_raise(cGzError, "closed gzip stream");
2925 }
2926 return gz;
2927 }
2928
2929
2930 /* ------------------------------------------------------------------------- */
2931
2932 /*
2933 * Document-class: Zlib::GzipFile
2934 *
2935 * Zlib::GzipFile is an abstract class for handling a gzip formatted
2936 * compressed file. The operations are defined in the subclasses,
2937 * Zlib::GzipReader for reading, and Zlib::GzipWriter for writing.
2938 *
2939 * GzipReader should be used by associating an IO, or IO-like, object.
2940 *
2941 * == Method Catalogue
2942 *
2943 * - ::wrap
2944 * - ::open (Zlib::GzipReader::open and Zlib::GzipWriter::open)
2945 * - #close
2946 * - #closed?
2947 * - #comment
2948 * - comment= (Zlib::GzipWriter#comment=)
2949 * - #crc
2950 * - eof? (Zlib::GzipReader#eof?)
2951 * - #finish
2952 * - #level
2953 * - lineno (Zlib::GzipReader#lineno)
2954 * - lineno= (Zlib::GzipReader#lineno=)
2955 * - #mtime
2956 * - mtime= (Zlib::GzipWriter#mtime=)
2957 * - #orig_name
2958 * - orig_name (Zlib::GzipWriter#orig_name=)
2959 * - #os_code
2960 * - path (when the underlying IO supports #path)
2961 * - #sync
2962 * - #sync=
2963 * - #to_io
2964 *
2965 * (due to internal structure, documentation may appear under Zlib::GzipReader
2966 * or Zlib::GzipWriter)
2967 */
2968
2969
2970 typedef struct {
2971 int argc;
2972 VALUE *argv;
2973 VALUE klass;
2974 } new_wrap_arg_t;
2975
2976 static VALUE
2977 new_wrap(VALUE tmp)
2978 {
2979 new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp;
2980 return rb_class_new_instance(arg->argc, arg->argv, arg->klass);
2981 }
2982
2983 static VALUE
2984 gzfile_ensure_close(VALUE obj)
2985 {
2986 struct gzfile *gz;
2987
2988 Data_Get_Struct(obj, struct gzfile, gz);
2989 if (ZSTREAM_IS_READY(&gz->z)) {
2990 gzfile_close(gz, 1);
2991 }
2992 return Qnil;
2993 }
2994
2995 static VALUE
2996 gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
2997 {
2998 VALUE obj;
2999
3000 if (close_io_on_error) {
3001 int state = 0;
3002 new_wrap_arg_t arg;
3003 arg.argc = argc;
3004 arg.argv = argv;
3005 arg.klass = klass;
3006 obj = rb_protect(new_wrap, (VALUE)&arg, &state);
3007 if (state) {
3008 rb_io_close(argv[0]);
3009 rb_jump_tag(state);
3010 }
3011 }
3012 else {
3013 obj = rb_class_new_instance(argc, argv, klass);
3014 }
3015
3016 if (rb_block_given_p()) {
3017 return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
3018 }
3019 else {
3020 return obj;
3021 }
3022 }
3023
3024 /*
3025 * Document-method: Zlib::GzipFile.wrap
3026 *
3027 * call-seq:
3028 * Zlib::GzipReader.wrap(io, ...) { |gz| ... }
3029 * Zlib::GzipWriter.wrap(io, ...) { |gz| ... }
3030 *
3031 * Creates a GzipReader or GzipWriter associated with +io+, passing in any
3032 * necessary extra options, and executes the block with the newly created
3033 * object just like File.open.
3034 *
3035 * The GzipFile object will be closed automatically after executing the block.
3036 * If you want to keep the associated IO object open, you may call
3037 * Zlib::GzipFile#finish method in the block.
3038 */
3039 static VALUE
3040 rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
3041 {
3042 return gzfile_wrap(argc, argv, klass, 0);
3043 }
3044
3045 /*
3046 * Document-method: Zlib::GzipFile.open
3047 *
3048 * See Zlib::GzipReader#open and Zlib::GzipWriter#open.
3049 */
3050 static VALUE
3051 gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
3052 {
3053 VALUE io, filename;
3054
3055 if (argc < 1) {
3056 rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
3057 }
3058 filename = argv[0];
3059 io = rb_file_open_str(filename, mode);
3060 argv[0] = io;
3061 return gzfile_wrap(argc, argv, klass, 1);
3062 }
3063
3064 /*
3065 * Document-method: Zlib::GzipFile#to_io
3066 *
3067 * Same as IO.
3068 */
3069 static VALUE
3070 rb_gzfile_to_io(VALUE obj)
3071 {
3072 return get_gzfile(obj)->io;
3073 }
3074
3075 /*
3076 * Document-method: Zlib::GzipFile#crc
3077 *
3078 * Returns CRC value of the uncompressed data.
3079 */
3080 static VALUE
3081 rb_gzfile_crc(VALUE obj)
3082 {
3083 return rb_uint2inum(get_gzfile(obj)->crc);
3084 }
3085
3086 /*
3087 * Document-method: Zlib::GzipFile#mtime
3088 *
3089 * Returns last modification time recorded in the gzip file header.
3090 */
3091 static VALUE
3092 rb_gzfile_mtime(VALUE obj)
3093 {
3094 return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
3095 }
3096
3097 /*
3098 * Document-method: Zlib::GzipFile#level
3099 *
3100 * Returns compression level.
3101 */
3102 static VALUE
3103 rb_gzfile_level(VALUE obj)
3104 {
3105 return INT2FIX(get_gzfile(obj)->level);
3106 }
3107
3108 /*
3109 * Document-method: Zlib::GzipFile#os_code
3110 *
3111 * Returns OS code number recorded in the gzip file header.
3112 */
3113 static VALUE
3114 rb_gzfile_os_code(VALUE obj)
3115 {
3116 return INT2FIX(get_gzfile(obj)->os_code);
3117 }
3118
3119 /*
3120 * Document-method: Zlib::GzipFile#orig_name
3121 *
3122 * Returns original filename recorded in the gzip file header, or +nil+ if
3123 * original filename is not present.
3124 */
3125 static VALUE
3126 rb_gzfile_orig_name(VALUE obj)
3127 {
3128 VALUE str = get_gzfile(obj)->orig_name;
3129 if (!NIL_P(str)) {
3130 str = rb_str_dup(str);
3131 }
3132 OBJ_TAINT(str); /* for safe */
3133 return str;
3134 }
3135
3136 /*
3137 * Document-method: Zlib::GzipFile#comment
3138 *
3139 * Returns comments recorded in the gzip file header, or nil if the comments
3140 * is not present.
3141 */
3142 static VALUE
3143 rb_gzfile_comment(VALUE obj)
3144 {
3145 VALUE str = get_gzfile(obj)->comment;
3146 if (!NIL_P(str)) {
3147 str = rb_str_dup(str);
3148 }
3149 OBJ_TAINT(str); /* for safe */
3150 return str;
3151 }
3152
3153 /*
3154 * Document-method: Zlib::GzipFile#lineno
3155 *
3156 * The line number of the last row read from this file.
3157 */
3158 static VALUE
3159 rb_gzfile_lineno(VALUE obj)
3160 {
3161 return INT2NUM(get_gzfile(obj)->lineno);
3162 }
3163
3164 /*
3165 * Document-method: Zlib::GzipReader#lineno=
3166 *
3167 * Specify line number of the last row read from this file.
3168 */
3169 static VALUE
3170 rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
3171 {
3172 struct gzfile *gz = get_gzfile(obj);
3173 gz->lineno = NUM2INT(lineno);
3174 return lineno;
3175 }
3176
3177 /*
3178 * Document-method: Zlib::GzipWriter#mtime=
3179 *
3180 * Specify the modification time (+mtime+) in the gzip header.
3181 * Using a Fixnum or Integer
3182 */
3183 static VALUE
3184 rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
3185 {
3186 struct gzfile *gz = get_gzfile(obj);
3187 VALUE val;
3188
3189 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
3190 rb_raise(cGzError, "header is already written");
3191 }
3192
3193 if (FIXNUM_P(mtime)) {
3194 gz->mtime = FIX2INT(mtime);
3195 }
3196 else {
3197 val = rb_Integer(mtime);
3198 gz->mtime = FIXNUM_P(val) ? FIX2UINT(val) : rb_big2ulong(val);
3199 }
3200 return mtime;
3201 }
3202
3203 /*
3204 * Document-method: Zlib::GzipFile#orig_name=
3205 *
3206 * Specify the original name (+str+) in the gzip header.
3207 */
3208 static VALUE
3209 rb_gzfile_set_orig_name(VALUE obj, VALUE str)
3210 {
3211 struct gzfile *gz = get_gzfile(obj);
3212 VALUE s;
3213 char *p;
3214
3215 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
3216 rb_raise(cGzError, "header is already written");
3217 }
3218 s = rb_str_dup(rb_str_to_str(str));
3219 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
3220 if (p) {
3221 rb_str_resize(s, p - RSTRING_PTR(s));
3222 }
3223 gz->orig_name = s;
3224 return str;
3225 }
3226
3227 /*
3228 * Document-method: Zlib::GzipFile#comment=
3229 *
3230 * Specify the comment (+str+) in the gzip header.
3231 */
3232 static VALUE
3233 rb_gzfile_set_comment(VALUE obj, VALUE str)
3234 {
3235 struct gzfile *gz = get_gzfile(obj);
3236 VALUE s;
3237 char *p;
3238
3239 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
3240 rb_raise(cGzError, "header is already written");
3241 }
3242 s = rb_str_dup(rb_str_to_str(str));
3243 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
3244 if (p) {
3245 rb_str_resize(s, p - RSTRING_PTR(s));
3246 }
3247 gz->comment = s;
3248 return str;
3249 }
3250
3251 /*
3252 * Document-method: Zlib::GzipFile#close
3253 *
3254 * Closes the GzipFile object. This method calls close method of the
3255 * associated IO object. Returns the associated IO object.
3256 */
3257 static VALUE
3258 rb_gzfile_close(VALUE obj)
3259 {
3260 struct gzfile *gz = get_gzfile(obj);
3261 VALUE io;
3262
3263 io = gz->io;
3264 gzfile_close(gz, 1);
3265 return io;
3266 }
3267
3268 /*
3269 * Document-method: Zlib::GzipFile#finish
3270 *
3271 * Closes the GzipFile object. Unlike Zlib::GzipFile#close, this method never
3272 * calls the close method of the associated IO object. Returns the associated IO
3273 * object.
3274 */
3275 static VALUE
3276 rb_gzfile_finish(VALUE obj)
3277 {
3278 struct gzfile *gz = get_gzfile(obj);
3279 VALUE io;
3280
3281 io = gz->io;
3282 gzfile_close(gz, 0);
3283 return io;
3284 }
3285
3286 /*
3287 * Document-method: Zlib::GzipFile#closed?
3288 *
3289 * Same as IO#closed?
3290 *
3291 */
3292 static VALUE
3293 rb_gzfile_closed_p(VALUE obj)
3294 {
3295 struct gzfile *gz;
3296 Data_Get_Struct(obj, struct gzfile, gz);
3297 return NIL_P(gz->io) ? Qtrue : Qfalse;
3298 }
3299
3300 /*
3301 * Document-method: Zlib::GzipFile#eof?
3302 *
3303 * Returns +true+ or +false+ whether the stream has reached the end.
3304 */
3305 static VALUE
3306 rb_gzfile_eof_p(VALUE obj)
3307 {
3308 struct gzfile *gz = get_gzfile(obj);
3309 return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
3310 }
3311
3312 /*
3313 * Document-method: Zlib::GzipFile#sync
3314 *
3315 * Same as IO#sync
3316 *
3317 */
3318 static VALUE
3319 rb_gzfile_sync(VALUE obj)
3320 {
3321 return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
3322 }
3323
3324 /*
3325 * Document-method: Zlib::GzipFile#sync=
3326 *
3327 * call-seq: sync = flag
3328 *
3329 * Same as IO. If flag is +true+, the associated IO object must respond to the
3330 * +flush+ method. While +sync+ mode is +true+, the compression ratio
3331 * decreases sharply.
3332 */
3333 static VALUE
3334 rb_gzfile_set_sync(VALUE obj, VALUE mode)
3335 {
3336 struct gzfile *gz = get_gzfile(obj);
3337
3338 if (RTEST(mode)) {
3339 gz->z.flags |= GZFILE_FLAG_SYNC;
3340 }
3341 else {
3342 gz->z.flags &= ~GZFILE_FLAG_SYNC;
3343 }
3344 return mode;
3345 }
3346
3347 /*
3348 * Document-method: Zlib::GzipFile#total_in
3349 *
3350 * Total number of input bytes read so far.
3351 */
3352 static VALUE
3353 rb_gzfile_total_in(VALUE obj)
3354 {
3355 return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
3356 }
3357
3358 /*
3359 * Document-method: Zlib::GzipFile#total_out
3360 *
3361 * Total number of output bytes output so far.
3362 */
3363 static VALUE
3364 rb_gzfile_total_out(VALUE obj)
3365 {
3366 struct gzfile *gz = get_gzfile(obj);
3367 return rb_uint2inum(gz->z.stream.total_out - gz->z.buf_filled);
3368 }
3369
3370 /*
3371 * Document-method: Zlib::GzipFile#path
3372 *
3373 * call-seq: path
3374 *
3375 * Returns the path string of the associated IO-like object. This
3376 * method is only defined when the IO-like object responds to #path().
3377 */
3378 static VALUE
3379 rb_gzfile_path(VALUE obj)
3380 {
3381 struct gzfile *gz;
3382 Data_Get_Struct(obj, struct gzfile, gz);
3383 return gz->path;
3384 }
3385
3386 static void
3387 rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
3388 {
3389 if (!NIL_P(opts)) {
3390 rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2, NULL);
3391 }
3392 if (gz->enc2) {
3393 gz->ecflags = rb_econv_prepare_opts(opts, &opts);
3394 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
3395 gz->ecflags, opts);
3396 gz->ecopts = opts;
3397 }
3398 }
3399
3400 /* ------------------------------------------------------------------------- */
3401
3402 /*
3403 * Document-class: Zlib::GzipWriter
3404 *
3405 * Zlib::GzipWriter is a class for writing gzipped files. GzipWriter should
3406 * be used with an instance of IO, or IO-like, object.
3407 *
3408 * Following two example generate the same result.
3409 *
3410 * Zlib::GzipWriter.open('hoge.gz') do |gz|
3411 * gz.write 'jugemu jugemu gokou no surikire...'
3412 * end
3413 *
3414 * File.open('hoge.gz', 'w') do |f|
3415 * gz = Zlib::GzipWriter.new(f)
3416 * gz.write 'jugemu jugemu gokou no surikire...'
3417 * gz.close
3418 * end
3419 *
3420 * To make like gzip(1) does, run following:
3421 *
3422 * orig = 'hoge.txt'
3423 * Zlib::GzipWriter.open('hoge.gz') do |gz|
3424 * gz.mtime = File.mtime(orig)
3425 * gz.orig_name = orig
3426 * gz.write IO.binread(orig)
3427 * end
3428 *
3429 * NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close
3430 * GzipWriter objects by Zlib::GzipWriter#close etc. Otherwise, GzipWriter
3431 * will be not able to write the gzip footer and will generate a broken gzip
3432 * file.
3433 */
3434
3435 static VALUE
3436 rb_gzwriter_s_allocate(VALUE klass)
3437 {
3438 return gzfile_writer_new(klass);
3439 }
3440
3441 /*
3442 * call-seq: Zlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... }
3443 *
3444 * Opens a file specified by +filename+ for writing gzip compressed data, and
3445 * returns a GzipWriter object associated with that file. Further details of
3446 * this method are found in Zlib::GzipWriter.new and Zlib::GzipFile.wrap.
3447 */
3448 static VALUE
3449 rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
3450 {
3451 return gzfile_s_open(argc, argv, klass, "wb");
3452 }
3453
3454 /*
3455 * call-seq:
3456 * Zlib::GzipWriter.new(io, level = nil, strategy = nil, options = {})
3457 *
3458 * Creates a GzipWriter object associated with +io+. +level+ and +strategy+
3459 * should be the same as the arguments of Zlib::Deflate.new. The GzipWriter
3460 * object writes gzipped data to +io+. +io+ must respond to the
3461 * +write+ method that behaves the same as IO#write.
3462 *
3463 * The +options+ hash may be used to set the encoding of the data.
3464 * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
3465 * IO::new.
3466 */
3467 static VALUE
3468 rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
3469 {
3470 struct gzfile *gz;
3471 VALUE io, level, strategy, opt = Qnil;
3472 int err;
3473
3474 if (argc > 1) {
3475 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
3476 if (!NIL_P(opt)) argc--;
3477 }
3478
3479 rb_scan_args(argc, argv, "12", &io, &level, &strategy);
3480 Data_Get_Struct(obj, struct gzfile, gz);
3481
3482 /* this is undocumented feature of zlib */
3483 gz->level = ARG_LEVEL(level);
3484 err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
3485 -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
3486 if (err != Z_OK) {
3487 raise_zlib_error(err, gz->z.stream.msg);
3488 }
3489 gz->io = io;
3490 ZSTREAM_READY(&gz->z);
3491 rb_gzfile_ecopts(gz, opt);
3492
3493 if (rb_respond_to(io, id_path)) {
3494 gz->path = rb_funcall(gz->io, id_path, 0);
3495 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3496 }
3497
3498 return obj;
3499 }
3500
3501 /*
3502 * call-seq: flush(flush=nil)
3503 *
3504 * Flushes all the internal buffers of the GzipWriter object. The meaning of
3505 * +flush+ is same as in Zlib::Deflate#deflate. <tt>Zlib::SYNC_FLUSH</tt> is used if
3506 * +flush+ is omitted. It is no use giving flush <tt>Zlib::NO_FLUSH</tt>.
3507 */
3508 static VALUE
3509 rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
3510 {
3511 struct gzfile *gz = get_gzfile(obj);
3512 VALUE v_flush;
3513 int flush;
3514
3515 rb_scan_args(argc, argv, "01", &v_flush);
3516
3517 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
3518 if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
3519 zstream_run(&gz->z, (Bytef*)"", 0, flush);
3520 }
3521
3522 gzfile_write_raw(gz);
3523 if (rb_respond_to(gz->io, id_flush)) {
3524 rb_funcall(gz->io, id_flush, 0);
3525 }
3526 return obj;
3527 }
3528
3529 /*
3530 * Same as IO.
3531 */
3532 static VALUE
3533 rb_gzwriter_write(VALUE obj, VALUE str)
3534 {
3535 struct gzfile *gz = get_gzfile(obj);
3536
3537 if (!RB_TYPE_P(str, T_STRING))
3538 str = rb_obj_as_string(str);
3539 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3540 str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
3541 }
3542 gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
3543 return INT2FIX(RSTRING_LEN(str));
3544 }
3545
3546 /*
3547 * Same as IO.
3548 */
3549 static VALUE
3550 rb_gzwriter_putc(VALUE obj, VALUE ch)
3551 {
3552 struct gzfile *gz = get_gzfile(obj);
3553 char c = NUM2CHR(ch);
3554
3555 gzfile_write(gz, (Bytef*)&c, 1);
3556 return ch;
3557 }
3558
3559
3560
3561 /*
3562 * Document-method: <<
3563 * Same as IO.
3564 */
3565 #define rb_gzwriter_addstr rb_io_addstr
3566 /*
3567 * Document-method: printf
3568 * Same as IO.
3569 */
3570 #define rb_gzwriter_printf rb_io_printf
3571 /*
3572 * Document-method: print
3573 * Same as IO.
3574 */
3575 #define rb_gzwriter_print rb_io_print
3576 /*
3577 * Document-method: puts
3578 * Same as IO.
3579 */
3580 #define rb_gzwriter_puts rb_io_puts
3581
3582
3583 /* ------------------------------------------------------------------------- */
3584
3585 /*
3586 * Document-class: Zlib::GzipReader
3587 *
3588 * Zlib::GzipReader is the class for reading a gzipped file. GzipReader should
3589 * be used an IO, or -IO-like, object.
3590 *
3591 * Zlib::GzipReader.open('hoge.gz') {|gz|
3592 * print gz.read
3593 * }
3594 *
3595 * File.open('hoge.gz') do |f|
3596 * gz = Zlib::GzipReader.new(f)
3597 * print gz.read
3598 * gz.close
3599 * end
3600 *
3601 * == Method Catalogue
3602 *
3603 * The following methods in Zlib::GzipReader are just like their counterparts
3604 * in IO, but they raise Zlib::Error or Zlib::GzipFile::Error exception if an
3605 * error was found in the gzip file.
3606 * - #each
3607 * - #each_line
3608 * - #each_byte
3609 * - #gets
3610 * - #getc
3611 * - #lineno
3612 * - #lineno=
3613 * - #read
3614 * - #readchar
3615 * - #readline
3616 * - #readlines
3617 * - #ungetc
3618 *
3619 * Be careful of the footer of the gzip file. A gzip file has the checksum of
3620 * pre-compressed data in its footer. GzipReader checks all uncompressed data
3621 * against that checksum at the following cases, and if it fails, raises
3622 * <tt>Zlib::GzipFile::NoFooter</tt>, <tt>Zlib::GzipFile::CRCError</tt>, or
3623 * <tt>Zlib::GzipFile::LengthError</tt> exception.
3624 *
3625 * - When an reading request is received beyond the end of file (the end of
3626 * compressed data). That is, when Zlib::GzipReader#read,
3627 * Zlib::GzipReader#gets, or some other methods for reading returns nil.
3628 * - When Zlib::GzipFile#close method is called after the object reaches the
3629 * end of file.
3630 * - When Zlib::GzipReader#unused method is called after the object reaches
3631 * the end of file.
3632 *
3633 * The rest of the methods are adequately described in their own
3634 * documentation.
3635 */
3636
3637 static VALUE
3638 rb_gzreader_s_allocate(VALUE klass)
3639 {
3640 return gzfile_reader_new(klass);
3641 }
3642
3643 /*
3644 * Document-method: Zlib::GzipReader.open
3645 *
3646 * call-seq: Zlib::GzipReader.open(filename) {|gz| ... }
3647 *
3648 * Opens a file specified by +filename+ as a gzipped file, and returns a
3649 * GzipReader object associated with that file. Further details of this method
3650 * are in Zlib::GzipReader.new and ZLib::GzipFile.wrap.
3651 */
3652 static VALUE
3653 rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
3654 {
3655 return gzfile_s_open(argc, argv, klass, "rb");
3656 }
3657
3658 /*
3659 * Document-method: Zlib::GzipReader.new
3660 *
3661 * call-seq:
3662 * Zlib::GzipReader.new(io, options = {})
3663 *
3664 * Creates a GzipReader object associated with +io+. The GzipReader object reads
3665 * gzipped data from +io+, and parses/decompresses it. The +io+ must
3666 * have a +read+ method that behaves same as the IO#read.
3667 *
3668 * The +options+ hash may be used to set the encoding of the data.
3669 * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
3670 * IO::new.
3671 *
3672 * If the gzip file header is incorrect, raises an Zlib::GzipFile::Error
3673 * exception.
3674 */
3675 static VALUE
3676 rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
3677 {
3678 VALUE io, opt = Qnil;
3679 struct gzfile *gz;
3680 int err;
3681
3682 Data_Get_Struct(obj, struct gzfile, gz);
3683 rb_scan_args(argc, argv, "1:", &io, &opt);
3684
3685 /* this is undocumented feature of zlib */
3686 err = inflateInit2(&gz->z.stream, -MAX_WBITS);
3687 if (err != Z_OK) {
3688 raise_zlib_error(err, gz->z.stream.msg);
3689 }
3690 gz->io = io;
3691 ZSTREAM_READY(&gz->z);
3692 gzfile_read_header(gz);
3693 rb_gzfile_ecopts(gz, opt);
3694
3695 if (rb_respond_to(io, id_path)) {
3696 gz->path = rb_funcall(gz->io, id_path, 0);
3697 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3698 }
3699
3700 return obj;
3701 }
3702
3703 /*
3704 * Document-method: Zlib::GzipReader#rewind
3705 *
3706 * Resets the position of the file pointer to the point created the GzipReader
3707 * object. The associated IO object needs to respond to the +seek+ method.
3708 */
3709 static VALUE
3710 rb_gzreader_rewind(VALUE obj)
3711 {
3712 struct gzfile *gz = get_gzfile(obj);
3713 gzfile_reader_rewind(gz);
3714 return INT2FIX(0);
3715 }
3716
3717 /*
3718 * Document-method: Zlib::GzipReader#unused
3719 *
3720 * Returns the rest of the data which had read for parsing gzip format, or
3721 * +nil+ if the whole gzip file is not parsed yet.
3722 */
3723 static VALUE
3724 rb_gzreader_unused(VALUE obj)
3725 {
3726 struct gzfile *gz;
3727 Data_Get_Struct(obj, struct gzfile, gz);
3728 return gzfile_reader_get_unused(gz);
3729 }
3730
3731 /*
3732 * Document-method: Zlib::GzipReader#read
3733 *
3734 * See Zlib::GzipReader documentation for a description.
3735 */
3736 static VALUE
3737 rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
3738 {
3739 struct gzfile *gz = get_gzfile(obj);
3740 VALUE vlen;
3741 long len;
3742
3743 rb_scan_args(argc, argv, "01", &vlen);
3744 if (NIL_P(vlen)) {
3745 return gzfile_read_all(gz);
3746 }
3747
3748 len = NUM2INT(vlen);
3749 if (len < 0) {
3750 rb_raise(rb_eArgError, "negative length %ld given", len);
3751 }
3752 return gzfile_read(gz, len);
3753 }
3754
3755 /*
3756 * Document-method: Zlib::GzipReader#readpartial
3757 *
3758 * call-seq:
3759 * gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
3760 *
3761 * Reads at most <i>maxlen</i> bytes from the gziped stream but
3762 * it blocks only if <em>gzipreader</em> has no data immediately available.
3763 * If the optional <i>outbuf</i> argument is present,
3764 * it must reference a String, which will receive the data.
3765 * It raises <code>EOFError</code> on end of file.
3766 */
3767 static VALUE
3768 rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
3769 {
3770 struct gzfile *gz = get_gzfile(obj);
3771 VALUE vlen, outbuf;
3772 long len;
3773
3774 rb_scan_args(argc, argv, "11", &vlen, &outbuf);
3775
3776 len = NUM2INT(vlen);
3777 if (len < 0) {
3778 rb_raise(rb_eArgError, "negative length %ld given", len);
3779 }
3780 if (!NIL_P(outbuf))
3781 Check_Type(outbuf, T_STRING);
3782 return gzfile_readpartial(gz, len, outbuf);
3783 }
3784
3785 /*
3786 * Document-method: Zlib::GzipReader#getc
3787 *
3788 * See Zlib::GzipReader documentation for a description.
3789 */
3790 static VALUE
3791 rb_gzreader_getc(VALUE obj)
3792 {
3793 struct gzfile *gz = get_gzfile(obj);
3794
3795 return gzfile_getc(gz);
3796 }
3797
3798 /*
3799 * Document-method: Zlib::GzipReader#readchar
3800 *
3801 * See Zlib::GzipReader documentation for a description.
3802 */
3803 static VALUE
3804 rb_gzreader_readchar(VALUE obj)
3805 {
3806 VALUE dst;
3807 dst = rb_gzreader_getc(obj);
3808 if (NIL_P(dst)) {
3809 rb_raise(rb_eEOFError, "end of file reached");
3810 }
3811 return dst;
3812 }
3813
3814 /*
3815 * Document-method: Zlib::GzipReader#getbyte
3816 *
3817 * See Zlib::GzipReader documentation for a description.
3818 */
3819 static VALUE
3820 rb_gzreader_getbyte(VALUE obj)
3821 {
3822 struct gzfile *gz = get_gzfile(obj);
3823 VALUE dst;
3824
3825 dst = gzfile_read(gz, 1);
3826 if (!NIL_P(dst)) {
3827 dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
3828 }
3829 return dst;
3830 }
3831
3832 /*
3833 * Document-method: Zlib::GzipReader#readbyte
3834 *
3835 * See Zlib::GzipReader documentation for a description.
3836 */
3837 static VALUE
3838 rb_gzreader_readbyte(VALUE obj)
3839 {
3840 VALUE dst;
3841 dst = rb_gzreader_getbyte(obj);
3842 if (NIL_P(dst)) {
3843 rb_raise(rb_eEOFError, "end of file reached");
3844 }
3845 return dst;
3846 }
3847
3848 /*
3849 * Document-method: Zlib::GzipReader#each_char
3850 *
3851 * See Zlib::GzipReader documentation for a description.
3852 */
3853 static VALUE
3854 rb_gzreader_each_char(VALUE obj)
3855 {
3856 VALUE c;
3857
3858 RETURN_ENUMERATOR(obj, 0, 0);
3859
3860 while (!NIL_P(c = rb_gzreader_getc(obj))) {
3861 rb_yield(c);
3862 }
3863 return Qnil;
3864 }
3865
3866 /*
3867 * Document-method: Zlib::GzipReader#each_byte
3868 *
3869 * See Zlib::GzipReader documentation for a description.
3870 */
3871 static VALUE
3872 rb_gzreader_each_byte(VALUE obj)
3873 {
3874 VALUE c;
3875
3876 RETURN_ENUMERATOR(obj, 0, 0);
3877
3878 while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
3879 rb_yield(c);
3880 }
3881 return Qnil;
3882 }
3883
3884 /*
3885 * Document-method: Zlib::GzipReader#bytes
3886 *
3887 * This is a deprecated alias for <code>each_byte</code>.
3888 */
3889 static VALUE
3890 rb_gzreader_bytes(VALUE obj)
3891 {
3892 rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
3893 if (!rb_block_given_p())
3894 return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
3895 return rb_gzreader_each_byte(obj);
3896 }
3897
3898 /*
3899 * Document-method: Zlib::GzipReader#ungetc
3900 *
3901 * See Zlib::GzipReader documentation for a description.
3902 */
3903 static VALUE
3904 rb_gzreader_ungetc(VALUE obj, VALUE s)
3905 {
3906 struct gzfile *gz;
3907
3908 if (FIXNUM_P(s))
3909 return rb_gzreader_ungetbyte(obj, s);
3910 gz = get_gzfile(obj);
3911 StringValue(s);
3912 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3913 s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
3914 }
3915 gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
3916 return Qnil;
3917 }
3918
3919 /*
3920 * Document-method: Zlib::GzipReader#ungetbyte
3921 *
3922 * See Zlib::GzipReader documentation for a description.
3923 */
3924 static VALUE
3925 rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
3926 {
3927 struct gzfile *gz = get_gzfile(obj);
3928 gzfile_ungetbyte(gz, NUM2CHR(ch));
3929 return Qnil;
3930 }
3931
3932 static void
3933 gzreader_skip_linebreaks(struct gzfile *gz)
3934 {
3935 VALUE str;
3936 char *p;
3937 int n;
3938
3939 while (gz->z.buf_filled == 0) {
3940 if (GZFILE_IS_FINISHED(gz)) return;
3941 gzfile_read_more(gz);
3942 }
3943 n = 0;
3944 p = RSTRING_PTR(gz->z.buf);
3945
3946 while (n++, *(p++) == '\n') {
3947 if (n >= gz->z.buf_filled) {
3948 str = zstream_detach_buffer(&gz->z);
3949 gzfile_calc_crc(gz, str);
3950 while (gz->z.buf_filled == 0) {
3951 if (GZFILE_IS_FINISHED(gz)) return;
3952 gzfile_read_more(gz);
3953 }
3954 n = 0;
3955 p = RSTRING_PTR(gz->z.buf);
3956 }
3957 }
3958
3959 str = zstream_shift_buffer(&gz->z, n - 1);
3960 gzfile_calc_crc(gz, str);
3961 }
3962
3963 static void
3964 rscheck(const char *rsptr, long rslen, VALUE rs)
3965 {
3966 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3967 rb_raise(rb_eRuntimeError, "rs modified");
3968 }
3969
3970 static long
3971 gzreader_charboundary(struct gzfile *gz, long n)
3972 {
3973 char *s = RSTRING_PTR(gz->z.buf);
3974 char *e = s + gz->z.buf_filled;
3975 char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
3976 long l = p - s;
3977 if (l < n) {
3978 n = rb_enc_precise_mbclen(p, e, gz->enc);
3979 if (MBCLEN_NEEDMORE_P(n)) {
3980 if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
3981 return l;
3982 }
3983 }
3984 else if (MBCLEN_CHARFOUND_P(n)) {
3985 return l + MBCLEN_CHARFOUND_LEN(n);
3986 }
3987 }
3988 return n;
3989 }
3990
3991 static VALUE
3992 gzreader_gets(int argc, VALUE *argv, VALUE obj)
3993 {
3994 struct gzfile *gz = get_gzfile(obj);
3995 volatile VALUE rs;
3996 VALUE dst;
3997 const char *rsptr;
3998 char *p, *res;
3999 long rslen, n, limit = -1;
4000 int rspara;
4001 rb_encoding *enc = gz->enc;
4002 int maxlen = rb_enc_mbmaxlen(enc);
4003
4004 if (argc == 0) {
4005 rs = rb_rs;
4006 }
4007 else {
4008 VALUE lim, tmp;
4009
4010 rb_scan_args(argc, argv, "11", &rs, &lim);
4011 if (!NIL_P(lim)) {
4012 if (!NIL_P(rs)) StringValue(rs);
4013 }
4014 else if (!NIL_P(rs)) {
4015 tmp = rb_check_string_type(rs);
4016 if (NIL_P(tmp)) {
4017 lim = rs;
4018 rs = rb_rs;
4019 }
4020 else {
4021 rs = tmp;
4022 }
4023 }
4024 if (!NIL_P(lim)) {
4025 limit = NUM2LONG(lim);
4026 if (limit == 0) return rb_str_new(0,0);
4027 }
4028 }
4029
4030 if (NIL_P(rs)) {
4031 if (limit < 0) {
4032 dst = gzfile_read_all(gz);
4033 if (RSTRING_LEN(dst) == 0) return Qnil;
4034 }
4035 else if ((n = gzfile_fill(gz, limit)) <= 0) {
4036 return Qnil;
4037 }
4038 else {
4039 if (maxlen > 1 && n >= limit && !GZFILE_IS_FINISHED(gz)) {
4040 n = gzreader_charboundary(gz, n);
4041 }
4042 else {
4043 n = limit;
4044 }
4045 dst = zstream_shift_buffer(&gz->z, n);
4046 if (NIL_P(dst)) return dst;
4047 gzfile_calc_crc(gz, dst);
4048 dst = gzfile_newstr(gz, dst);
4049 }
4050 gz->lineno++;
4051 return dst;
4052 }
4053
4054 if (RSTRING_LEN(rs) == 0) {
4055 rsptr = "\n\n";
4056 rslen = 2;
4057 rspara = 1;
4058 } else {
4059 rsptr = RSTRING_PTR(rs);
4060 rslen = RSTRING_LEN(rs);
4061 rspara = 0;
4062 }
4063
4064 if (rspara) {
4065 gzreader_skip_linebreaks(gz);
4066 }
4067
4068 while (gz->z.buf_filled < rslen) {
4069 if (ZSTREAM_IS_FINISHED(&gz->z)) {
4070 if (gz->z.buf_filled > 0) gz->lineno++;
4071 return gzfile_read(gz, rslen);
4072 }
4073 gzfile_read_more(gz);
4074 }
4075
4076 p = RSTRING_PTR(gz->z.buf);
4077 n = rslen;
4078 for (;;) {
4079 long filled;
4080 if (n > gz->z.buf_filled) {
4081 if (ZSTREAM_IS_FINISHED(&gz->z)) break;
4082 gzfile_read_more(gz);
4083 p = RSTRING_PTR(gz->z.buf) + n - rslen;
4084 }
4085 if (!rspara) rscheck(rsptr, rslen, rs);
4086 filled = gz->z.buf_filled;
4087 if (limit > 0 && filled >= limit) {
4088 filled = limit;
4089 }
4090 res = memchr(p, rsptr[0], (filled - n + 1));
4091 if (!res) {
4092 n = filled;
4093 if (limit > 0 && filled >= limit) break;
4094 n++;
4095 } else {
4096 n += (long)(res - p);
4097 p = res;
4098 if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
4099 p++, n++;
4100 }
4101 }
4102 if (maxlen > 1 && n == limit && (gz->z.buf_filled > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
4103 n = gzreader_charboundary(gz, n);
4104 }
4105
4106 gz->lineno++;
4107 dst = gzfile_read(gz, n);
4108 if (NIL_P(dst)) return dst;
4109 if (rspara) {
4110 gzreader_skip_linebreaks(gz);
4111 }
4112
4113 return gzfile_newstr(gz, dst);
4114 }
4115
4116 /*
4117 * Document-method: Zlib::GzipReader#gets
4118 *
4119 * See Zlib::GzipReader documentation for a description.
4120 */
4121 static VALUE
4122 rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
4123 {
4124 VALUE dst;
4125 dst = gzreader_gets(argc, argv, obj);
4126 if (!NIL_P(dst)) {
4127 rb_lastline_set(dst);
4128 }
4129 return dst;
4130 }
4131
4132 /*
4133 * Document-method: Zlib::GzipReader#readline
4134 *
4135 * See Zlib::GzipReader documentation for a description.
4136 */
4137 static VALUE
4138 rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
4139 {
4140 VALUE dst;
4141 dst = rb_gzreader_gets(argc, argv, obj);
4142 if (NIL_P(dst)) {
4143 rb_raise(rb_eEOFError, "end of file reached");
4144 }
4145 return dst;
4146 }
4147
4148 /*
4149 * Document-method: Zlib::GzipReader#each
4150 *
4151 * See Zlib::GzipReader documentation for a description.
4152 */
4153 static VALUE
4154 rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
4155 {
4156 VALUE str;
4157
4158 RETURN_ENUMERATOR(obj, 0, 0);
4159
4160 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
4161 rb_yield(str);
4162 }
4163 return obj;
4164 }
4165
4166 /*
4167 * Document-method: Zlib::GzipReader#lines
4168 *
4169 * This is a deprecated alias for <code>each_line</code>.
4170 */
4171 static VALUE
4172 rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
4173 {
4174 rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
4175 if (!rb_block_given_p())
4176 return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
4177 return rb_gzreader_each(argc, argv, obj);
4178 }
4179
4180 /*
4181 * Document-method: Zlib::GzipReader#readlines
4182 *
4183 * See Zlib::GzipReader documentation for a description.
4184 */
4185 static VALUE
4186 rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
4187 {
4188 VALUE str, dst;
4189 dst = rb_ary_new();
4190 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
4191 rb_ary_push(dst, str);
4192 }
4193 return dst;
4194 }
4195
4196 #endif /* GZIP_SUPPORT */
4197
4198 void
4199 Init_zlib()
4200 {
4201 VALUE mZlib, cZStream, cDeflate, cInflate;
4202 #if GZIP_SUPPORT
4203 VALUE cGzipFile, cGzipWriter, cGzipReader;
4204 #endif
4205
4206 mZlib = rb_define_module("Zlib");
4207
4208 id_dictionaries = rb_intern("@dictionaries");
4209
4210 cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
4211 cStreamEnd = rb_define_class_under(mZlib, "StreamEnd", cZError);
4212 cNeedDict = rb_define_class_under(mZlib, "NeedDict", cZError);
4213 cDataError = rb_define_class_under(mZlib, "DataError", cZError);
4214 cStreamError = rb_define_class_under(mZlib, "StreamError", cZError);
4215 cMemError = rb_define_class_under(mZlib, "MemError", cZError);
4216 cBufError = rb_define_class_under(mZlib, "BufError", cZError);
4217 cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
4218
4219 rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
4220 rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
4221 rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
4222 rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
4223 rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
4224 rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
4225
4226 /* The Ruby/zlib version string. */
4227 rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
4228 /* The string which represents the version of zlib.h */
4229 rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
4230
4231 cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
4232 rb_undef_alloc_func(cZStream);
4233 rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
4234 rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
4235 rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
4236 rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
4237 rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
4238 rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
4239 rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
4240 rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
4241 rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
4242 rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
4243 rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
4244 rb_define_method(cZStream, "close", rb_zstream_end, 0);
4245 rb_define_method(cZStream, "end", rb_zstream_end, 0);
4246 rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
4247 rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
4248 rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
4249 rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
4250
4251 /* Represents binary data as guessed by deflate.
4252 *
4253 * See Zlib::Deflate#data_type. */
4254 rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
4255
4256 /* Represents text data as guessed by deflate.
4257 *
4258 * NOTE: The underlying constant Z_ASCII was deprecated in favor of Z_TEXT
4259 * in zlib 1.2.2. New applications should not use this constant.
4260 *
4261 * See Zlib::Deflate#data_type. */
4262 rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
4263
4264 #ifdef Z_TEXT
4265 /* Represents text data as guessed by deflate.
4266 *
4267 * See Zlib::Deflate#data_type. */
4268 rb_define_const(mZlib, "TEXT", INT2FIX(Z_TEXT));
4269 #endif
4270
4271 /* Represents an unknown data type as guessed by deflate.
4272 *
4273 * See Zlib::Deflate#data_type. */
4274 rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
4275
4276 cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
4277 rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
4278 rb_define_singleton_method(mZlib, "deflate", rb_deflate_s_deflate, -1);
4279 rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
4280 rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
4281 rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
4282 rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
4283 rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
4284 rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
4285 rb_define_method(cDeflate, "params", rb_deflate_params, 2);
4286 rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
4287
4288 cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
4289 rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
4290 rb_define_singleton_method(mZlib, "inflate", rb_inflate_s_inflate, 1);
4291 rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
4292 rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
4293 rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
4294 rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
4295 rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
4296 rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
4297 rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
4298 rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
4299
4300 /* No compression, passes through data untouched. Use this for appending
4301 * pre-compressed data to a deflate stream.
4302 */
4303 rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
4304 /* Fastest compression level, but with with lowest space savings. */
4305 rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
4306 /* Slowest compression level, but with the best space savings. */
4307 rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
4308 /* Default compression level which is a good trade-off between space and
4309 * time
4310 */
4311 rb_define_const(mZlib, "DEFAULT_COMPRESSION",
4312 INT2FIX(Z_DEFAULT_COMPRESSION));
4313
4314 /* Deflate strategy for data produced by a filter (or predictor). The
4315 * effect of FILTERED is to force more Huffman codes and less string
4316 * matching; it is somewhat intermediate between DEFAULT_STRATEGY and
4317 * HUFFMAN_ONLY. Filtered data consists mostly of small values with a
4318 * somewhat random distribution.
4319 */
4320 rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
4321
4322 /* Deflate strategy which uses Huffman codes only (no string matching). */
4323 rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
4324
4325 #ifdef Z_RLE
4326 /* Deflate compression strategy designed to be almost as fast as
4327 * HUFFMAN_ONLY, but give better compression for PNG image data.
4328 */
4329 rb_define_const(mZlib, "RLE", INT2FIX(Z_RLE));
4330 #endif
4331
4332 #ifdef Z_FIXED
4333 /* Deflate strategy which prevents the use of dynamic Huffman codes,
4334 * allowing for a simpler decoder for specialized applications.
4335 */
4336 rb_define_const(mZlib, "FIXED", INT2FIX(Z_FIXED));
4337 #endif
4338
4339 /* Default deflate strategy which is used for normal data. */
4340 rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
4341
4342 /* The maximum size of the zlib history buffer. Note that zlib allows
4343 * larger values to enable different inflate modes. See Zlib::Inflate.new
4344 * for details.
4345 */
4346 rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
4347
4348 /* The default memory level for allocating zlib deflate compression state.
4349 */
4350 rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
4351
4352 /* The maximum memory level for allocating zlib deflate compression state.
4353 */
4354 rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
4355
4356 /* NO_FLUSH is the default flush method and allows deflate to decide how
4357 * much data to accumulate before producing output in order to maximize
4358 * compression.
4359 */
4360 rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
4361
4362 /* The SYNC_FLUSH method flushes all pending output to the output buffer
4363 * and the output is aligned on a byte boundary. Flushing may degrade
4364 * compression so it should be used only when necessary, such as at a
4365 * request or response boundary for a network stream.
4366 */
4367 rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
4368
4369 /* Flushes all output as with SYNC_FLUSH, and the compression state is
4370 * reset so that decompression can restart from this point if previous
4371 * compressed data has been damaged or if random access is desired. Like
4372 * SYNC_FLUSH, using FULL_FLUSH too often can seriously degrade
4373 * compression.
4374 */
4375 rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
4376
4377 /* Processes all pending input and flushes pending output. */
4378 rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
4379
4380 #if GZIP_SUPPORT
4381 id_write = rb_intern("write");
4382 id_read = rb_intern("read");
4383 id_readpartial = rb_intern("readpartial");
4384 id_flush = rb_intern("flush");
4385 id_seek = rb_intern("seek");
4386 id_close = rb_intern("close");
4387 id_path = rb_intern("path");
4388 id_input = rb_intern("@input");
4389
4390 cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
4391 cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
4392
4393 /* input gzipped string */
4394 rb_define_attr(cGzError, "input", 1, 0);
4395 rb_define_method(cGzError, "inspect", gzfile_error_inspect, 0);
4396
4397 cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
4398 cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
4399 cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
4400
4401 cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
4402 cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
4403 rb_include_module(cGzipReader, rb_mEnumerable);
4404
4405 rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
4406 rb_undef_alloc_func(cGzipFile);
4407 rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
4408 rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
4409 rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
4410 rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
4411 rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
4412 rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
4413 rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
4414 rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
4415 rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
4416 rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
4417 rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
4418 rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
4419 rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
4420 rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
4421 rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
4422 rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
4423 rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
4424 rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
4425 rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
4426 rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
4427 rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
4428 rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
4429 rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
4430
4431 rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
4432 rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
4433 rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
4434 rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
4435 rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
4436 rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
4437 rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
4438 rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
4439 rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
4440 rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
4441
4442 rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
4443 rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
4444 rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
4445 rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
4446 rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
4447 rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
4448 rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
4449 rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
4450 rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
4451 rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
4452 rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
4453 rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
4454 rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
4455 rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
4456 rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
4457 rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
4458 rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
4459 rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
4460 rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
4461 rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
4462 rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
4463 rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
4464
4465 /* The OS code of current host */
4466 rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
4467 /* OS code for MSDOS hosts */
4468 rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
4469 /* OS code for Amiga hosts */
4470 rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
4471 /* OS code for VMS hosts */
4472 rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
4473 /* OS code for UNIX hosts */
4474 rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
4475 /* OS code for Atari hosts */
4476 rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
4477 /* OS code for OS2 hosts */
4478 rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
4479 /* OS code for Mac OS hosts */
4480 rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
4481 /* OS code for TOPS-20 hosts */
4482 rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
4483 /* OS code for Win32 hosts */
4484 rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
4485 /* OS code for VM OS hosts */
4486 rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
4487 /* OS code for Z-System hosts */
4488 rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
4489 /* OS code for CP/M hosts */
4490 rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
4491 /* OS code for QDOS hosts */
4492 rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
4493 /* OS code for RISC OS hosts */
4494 rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
4495 /* OS code for unknown hosts */
4496 rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
4497
4498 #endif /* GZIP_SUPPORT */
4499 }
4500
4501 /* Document error classes. */
4502
4503 /*
4504 * Document-class: Zlib::Error
4505 *
4506 * The superclass for all exceptions raised by Ruby/zlib.
4507 *
4508 * The following exceptions are defined as subclasses of Zlib::Error. These
4509 * exceptions are raised when zlib library functions return with an error
4510 * status.
4511 *
4512 * - Zlib::StreamEnd
4513 * - Zlib::NeedDict
4514 * - Zlib::DataError
4515 * - Zlib::StreamError
4516 * - Zlib::MemError
4517 * - Zlib::BufError
4518 * - Zlib::VersionError
4519 *
4520 */
4521
4522 /*
4523 * Document-class: Zlib::StreamEnd
4524 *
4525 * Subclass of Zlib::Error
4526 *
4527 * When zlib returns a Z_STREAM_END
4528 * is return if the end of the compressed data has been reached
4529 * and all uncompressed out put has been produced.
4530 *
4531 */
4532
4533 /*
4534 * Document-class: Zlib::NeedDict
4535 *
4536 * Subclass of Zlib::Error
4537 *
4538 * When zlib returns a Z_NEED_DICT
4539 * if a preset dictionary is needed at this point.
4540 *
4541 * Used by Zlib::Inflate.inflate and <tt>Zlib.inflate</tt>
4542 */
4543
4544 /*
4545 * Document-class: Zlib::VersionError
4546 *
4547 * Subclass of Zlib::Error
4548 *
4549 * When zlib returns a Z_VERSION_ERROR,
4550 * usually if the zlib library version is incompatible with the
4551 * version assumed by the caller.
4552 *
4553 */
4554
4555 /*
4556 * Document-class: Zlib::MemError
4557 *
4558 * Subclass of Zlib::Error
4559 *
4560 * When zlib returns a Z_MEM_ERROR,
4561 * usually if there was not enough memory.
4562 *
4563 */
4564
4565 /*
4566 * Document-class: Zlib::StreamError
4567 *
4568 * Subclass of Zlib::Error
4569 *
4570 * When zlib returns a Z_STREAM_ERROR,
4571 * usually if the stream state was inconsistent.
4572 *
4573 */
4574
4575 /*
4576 * Document-class: Zlib::BufError
4577 *
4578 * Subclass of Zlib::Error when zlib returns a Z_BUF_ERROR.
4579 *
4580 * Usually if no progress is possible.
4581 *
4582 */
4583
4584 /*
4585 * Document-class: Zlib::DataError
4586 *
4587 * Subclass of Zlib::Error when zlib returns a Z_DATA_ERROR.
4588 *
4589 * Usually if a stream was prematurely freed.
4590 *
4591 */
4592
4593 /*
4594 * Document-class: Zlib::GzipFile::Error
4595 *
4596 * Base class of errors that occur when processing GZIP files.
4597 */
4598
4599 /*
4600 * Document-class: Zlib::GzipFile::NoFooter
4601 *
4602 * Raised when gzip file footer is not found.
4603 */
4604
4605 /*
4606 * Document-class: Zlib::GzipFile::CRCError
4607 *
4608 * Raised when the CRC checksum recorded in gzip file footer is not equivalent
4609 * to the CRC checksum of the actual uncompressed data.
4610 */
4611
4612 /*
4613 * Document-class: Zlib::GzipFile::LengthError
4614 *
4615 * Raised when the data length recorded in the gzip file footer is not equivalent
4616 * to the length of the actual uncompressed data.
4617 */
4618
4619
4620