1/*
2 * zlib.c - An interface for zlib.
3 *
4 *   Copyright (C) UENO Katsuhiro 2000-2003
5 *
6 * $Id: zlib.c 45096 2014-02-22 02:49:01Z 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
47static inline uInt
48max_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
60static ID id_dictionaries;
61
62/*--------- Prototypes --------*/
63
64static NORETURN(void raise_zlib_error(int, const char*));
65static VALUE rb_zlib_version(VALUE);
66static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
67static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
68static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
69static VALUE rb_zlib_crc_table(VALUE);
70static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
71static void zlib_mem_free(voidpf, voidpf);
72static void finalizer_warn(const char*);
73
74struct zstream;
75struct zstream_funcs;
76struct zstream_run_args;
77static void zstream_init(struct zstream*, const struct zstream_funcs*);
78static void zstream_expand_buffer(struct zstream*);
79static void zstream_expand_buffer_into(struct zstream*, unsigned long);
80static void zstream_append_buffer(struct zstream*, const Bytef*, long);
81static VALUE zstream_detach_buffer(struct zstream*);
82static VALUE zstream_shift_buffer(struct zstream*, long);
83static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
84static void zstream_buffer_ungetbyte(struct zstream*, int);
85static void zstream_append_input(struct zstream*, const Bytef*, long);
86static void zstream_discard_input(struct zstream*, long);
87static void zstream_reset_input(struct zstream*);
88static void zstream_passthrough_input(struct zstream*);
89static VALUE zstream_detach_input(struct zstream*);
90static void zstream_reset(struct zstream*);
91static VALUE zstream_end(struct zstream*);
92static void zstream_run(struct zstream*, Bytef*, long, int);
93static VALUE zstream_sync(struct zstream*, Bytef*, long);
94static void zstream_mark(struct zstream*);
95static void zstream_free(struct zstream*);
96static VALUE zstream_new(VALUE, const struct zstream_funcs*);
97static struct zstream *get_zstream(VALUE);
98static void zstream_finalize(struct zstream*);
99
100static VALUE rb_zstream_end(VALUE);
101static VALUE rb_zstream_reset(VALUE);
102static VALUE rb_zstream_finish(VALUE);
103static VALUE rb_zstream_flush_next_in(VALUE);
104static VALUE rb_zstream_flush_next_out(VALUE);
105static VALUE rb_zstream_avail_out(VALUE);
106static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
107static VALUE rb_zstream_avail_in(VALUE);
108static VALUE rb_zstream_total_in(VALUE);
109static VALUE rb_zstream_total_out(VALUE);
110static VALUE rb_zstream_data_type(VALUE);
111static VALUE rb_zstream_adler(VALUE);
112static VALUE rb_zstream_finished_p(VALUE);
113static VALUE rb_zstream_closed_p(VALUE);
114
115static VALUE rb_deflate_s_allocate(VALUE);
116static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
117static VALUE rb_deflate_init_copy(VALUE, VALUE);
118static VALUE deflate_run(VALUE);
119static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
120static void do_deflate(struct zstream*, VALUE, int);
121static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
122static VALUE rb_deflate_addstr(VALUE, VALUE);
123static VALUE rb_deflate_flush(int, VALUE*, VALUE);
124static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
125static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
126
127static VALUE inflate_run(VALUE);
128static VALUE rb_inflate_s_allocate(VALUE);
129static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
130static VALUE rb_inflate_s_inflate(VALUE, VALUE);
131static void do_inflate(struct zstream*, VALUE);
132static VALUE rb_inflate_inflate(VALUE, VALUE);
133static VALUE rb_inflate_addstr(VALUE, VALUE);
134static VALUE rb_inflate_sync(VALUE, VALUE);
135static VALUE rb_inflate_sync_point_p(VALUE);
136static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
137
138#if GZIP_SUPPORT
139struct gzfile;
140static void gzfile_mark(struct gzfile*);
141static void gzfile_free(struct gzfile*);
142static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
143static void gzfile_reset(struct gzfile*);
144static void gzfile_close(struct gzfile*, int);
145static void gzfile_write_raw(struct gzfile*);
146static VALUE gzfile_read_raw_partial(VALUE);
147static VALUE gzfile_read_raw_rescue(VALUE);
148static VALUE gzfile_read_raw(struct gzfile*);
149static int gzfile_read_raw_ensure(struct gzfile*, long);
150static char *gzfile_read_raw_until_zero(struct gzfile*, long);
151static unsigned int gzfile_get16(const unsigned char*);
152static unsigned long gzfile_get32(const unsigned char*);
153static void gzfile_set32(unsigned long n, unsigned char*);
154static void gzfile_make_header(struct gzfile*);
155static void gzfile_make_footer(struct gzfile*);
156static void gzfile_read_header(struct gzfile*);
157static void gzfile_check_footer(struct gzfile*);
158static void gzfile_write(struct gzfile*, Bytef*, long);
159static long gzfile_read_more(struct gzfile*);
160static void gzfile_calc_crc(struct gzfile*, VALUE);
161static VALUE gzfile_read(struct gzfile*, long);
162static VALUE gzfile_read_all(struct gzfile*);
163static void gzfile_ungets(struct gzfile*, const Bytef*, long);
164static void gzfile_ungetbyte(struct gzfile*, int);
165static VALUE gzfile_writer_end_run(VALUE);
166static void gzfile_writer_end(struct gzfile*);
167static VALUE gzfile_reader_end_run(VALUE);
168static void gzfile_reader_end(struct gzfile*);
169static void gzfile_reader_rewind(struct gzfile*);
170static VALUE gzfile_reader_get_unused(struct gzfile*);
171static struct gzfile *get_gzfile(VALUE);
172static VALUE gzfile_ensure_close(VALUE);
173static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
174static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
175NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *));
176static VALUE gzfile_error_inspect(VALUE);
177
178static VALUE rb_gzfile_to_io(VALUE);
179static VALUE rb_gzfile_crc(VALUE);
180static VALUE rb_gzfile_mtime(VALUE);
181static VALUE rb_gzfile_level(VALUE);
182static VALUE rb_gzfile_os_code(VALUE);
183static VALUE rb_gzfile_orig_name(VALUE);
184static VALUE rb_gzfile_comment(VALUE);
185static VALUE rb_gzfile_lineno(VALUE);
186static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
187static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
188static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
189static VALUE rb_gzfile_set_comment(VALUE, VALUE);
190static VALUE rb_gzfile_close(VALUE);
191static VALUE rb_gzfile_finish(VALUE);
192static VALUE rb_gzfile_closed_p(VALUE);
193static VALUE rb_gzfile_eof_p(VALUE);
194static VALUE rb_gzfile_sync(VALUE);
195static VALUE rb_gzfile_set_sync(VALUE, VALUE);
196static VALUE rb_gzfile_total_in(VALUE);
197static VALUE rb_gzfile_total_out(VALUE);
198static VALUE rb_gzfile_path(VALUE);
199
200static VALUE rb_gzwriter_s_allocate(VALUE);
201static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
202static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
203static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
204static VALUE rb_gzwriter_write(VALUE, VALUE);
205static VALUE rb_gzwriter_putc(VALUE, VALUE);
206
207static VALUE rb_gzreader_s_allocate(VALUE);
208static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
209static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
210static VALUE rb_gzreader_rewind(VALUE);
211static VALUE rb_gzreader_unused(VALUE);
212static VALUE rb_gzreader_read(int, VALUE*, VALUE);
213static VALUE rb_gzreader_getc(VALUE);
214static VALUE rb_gzreader_readchar(VALUE);
215static VALUE rb_gzreader_each_byte(VALUE);
216static VALUE rb_gzreader_ungetc(VALUE, VALUE);
217static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
218static void gzreader_skip_linebreaks(struct gzfile*);
219static VALUE gzreader_gets(int, VALUE*, VALUE);
220static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
221static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
222static VALUE rb_gzreader_each(int, VALUE*, VALUE);
223static 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 */
298void Init_zlib(void);
299
300/*--------- Exceptions --------*/
301
302static VALUE cZError, cStreamEnd, cNeedDict;
303static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
304
305static void
306raise_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	exc = rb_exc_new3(cZError,
341			     rb_sprintf("unknown zlib error %d: %s", err, msg));
342    }
343
344    rb_exc_raise(exc);
345}
346
347
348/*--- Warning (in finalizer) ---*/
349
350static void
351finalizer_warn(const char *msg)
352{
353    fprintf(stderr, "zlib(finalizer): %s\n", msg);
354}
355
356
357/*-------- module Zlib --------*/
358
359/*
360 * Document-method: Zlib.zlib_version
361 *
362 * Returns the string which represents the version of zlib library.
363 */
364static VALUE
365rb_zlib_version(VALUE klass)
366{
367    VALUE str;
368
369    str = rb_str_new2(zlibVersion());
370    OBJ_TAINT(str);  /* for safe */
371    return str;
372}
373
374#if SIZEOF_LONG > SIZEOF_INT
375static uLong
376checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
377{
378    if (len > UINT_MAX) {
379	do {
380	    sum = func(sum, ptr, UINT_MAX);
381	    ptr += UINT_MAX;
382	    len -= UINT_MAX;
383	} while (len >= UINT_MAX);
384    }
385    if (len > 0) sum = func(sum, ptr, (uInt)len);
386    return sum;
387}
388#else
389#define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
390#endif
391
392static VALUE
393do_checksum(argc, argv, func)
394    int argc;
395    VALUE *argv;
396    uLong (*func)(uLong, const Bytef*, uInt);
397{
398    VALUE str, vsum;
399    unsigned long sum;
400
401    rb_scan_args(argc, argv, "02", &str, &vsum);
402
403    if (!NIL_P(vsum)) {
404	sum = NUM2ULONG(vsum);
405    }
406    else if (NIL_P(str)) {
407	sum = 0;
408    }
409    else {
410	sum = func(0, Z_NULL, 0);
411    }
412
413    if (NIL_P(str)) {
414	sum = func(sum, Z_NULL, 0);
415    }
416    else {
417	StringValue(str);
418	sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
419    }
420    return rb_uint2inum(sum);
421}
422
423/*
424 * Document-method: Zlib.adler32
425 *
426 * call-seq: Zlib.adler32(string, adler)
427 *
428 * Calculates Adler-32 checksum for +string+, and returns updated value of
429 * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
430 * +adler+ is omitted, it assumes that the initial value is given to +adler+.
431 *
432 * FIXME: expression.
433 */
434static VALUE
435rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
436{
437    return do_checksum(argc, argv, adler32);
438}
439
440#ifdef HAVE_ADLER32_COMBINE
441/*
442 * Document-method: Zlib.adler32_combine
443 *
444 * call-seq: Zlib.adler32_combine(adler1, adler2, len2)
445 *
446 * Combine two Adler-32 check values in to one.  +alder1+ is the first Adler-32
447 * value, +adler2+ is the second Adler-32 value.  +len2+ is the length of the
448 * string used to generate +adler2+.
449 *
450 */
451static VALUE
452rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
453{
454  return ULONG2NUM(
455	adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
456}
457#else
458#define rb_zlib_adler32_combine rb_f_notimplement
459#endif
460
461/*
462 * Document-method: Zlib.crc32
463 *
464 * call-seq: Zlib.crc32(string, adler)
465 *
466 * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
467 * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
468 * assumes that the initial value is given to +crc+.
469 *
470 * FIXME: expression.
471 */
472static VALUE
473rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
474{
475    return do_checksum(argc, argv, crc32);
476}
477
478#ifdef HAVE_CRC32_COMBINE
479/*
480 * Document-method: Zlib.crc32_combine
481 *
482 * call-seq: Zlib.crc32_combine(crc1, crc2, len2)
483 *
484 * Combine two CRC-32 check values in to one.  +crc1+ is the first CRC-32
485 * value, +crc2+ is the second CRC-32 value.  +len2+ is the length of the
486 * string used to generate +crc2+.
487 *
488 */
489static VALUE
490rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
491{
492  return ULONG2NUM(
493	crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
494}
495#else
496#define rb_zlib_crc32_combine rb_f_notimplement
497#endif
498
499/*
500 * Document-method: Zlib.crc_table
501 *
502 * Returns the table for calculating CRC checksum as an array.
503 */
504static VALUE
505rb_zlib_crc_table(VALUE obj)
506{
507#if !defined(HAVE_TYPE_Z_CRC_T)
508    /* z_crc_t is defined since zlib-1.2.7. */
509    typedef unsigned long z_crc_t;
510#endif
511    const z_crc_t *crctbl;
512    VALUE dst;
513    int i;
514
515    crctbl = get_crc_table();
516    dst = rb_ary_new2(256);
517
518    for (i = 0; i < 256; i++) {
519	rb_ary_push(dst, rb_uint2inum(crctbl[i]));
520    }
521    return dst;
522}
523
524
525
526/*-------- zstream - internal APIs --------*/
527
528struct zstream {
529    unsigned long flags;
530    VALUE buf;
531    long buf_filled;
532    VALUE input;
533    z_stream stream;
534    const struct zstream_funcs {
535	int (*reset)(z_streamp);
536	int (*end)(z_streamp);
537	int (*run)(z_streamp, int);
538    } *func;
539};
540
541#define ZSTREAM_FLAG_READY      0x1
542#define ZSTREAM_FLAG_IN_STREAM  0x2
543#define ZSTREAM_FLAG_FINISHED   0x4
544#define ZSTREAM_FLAG_CLOSING    0x8
545#define ZSTREAM_FLAG_GZFILE     0x10 /* disallows yield from expand_buffer for
546                                        gzip*/
547#define ZSTREAM_FLAG_UNUSED     0x20
548
549#define ZSTREAM_READY(z)       ((z)->flags |= ZSTREAM_FLAG_READY)
550#define ZSTREAM_IS_READY(z)    ((z)->flags & ZSTREAM_FLAG_READY)
551#define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
552#define ZSTREAM_IS_CLOSING(z)  ((z)->flags & ZSTREAM_FLAG_CLOSING)
553#define ZSTREAM_IS_GZFILE(z)   ((z)->flags & ZSTREAM_FLAG_GZFILE)
554
555#define ZSTREAM_EXPAND_BUFFER_OK          0
556
557/* I think that more better value should be found,
558   but I gave up finding it. B) */
559#define ZSTREAM_INITIAL_BUFSIZE       1024
560/* Allow a quick return when the thread is interrupted */
561#define ZSTREAM_AVAIL_OUT_STEP_MAX   16384
562#define ZSTREAM_AVAIL_OUT_STEP_MIN    2048
563
564static const struct zstream_funcs deflate_funcs = {
565    deflateReset, deflateEnd, deflate,
566};
567
568static const struct zstream_funcs inflate_funcs = {
569    inflateReset, inflateEnd, inflate,
570};
571
572struct zstream_run_args {
573    struct zstream * z;
574    int flush;         /* stream flush value for inflate() or deflate() */
575    int interrupt;     /* stop processing the stream and return to ruby */
576    int jump_state;    /* for buffer expansion block break or exception */
577    int stream_output; /* for streaming zlib processing */
578};
579
580static voidpf
581zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
582{
583    voidpf p = xmalloc(items * size);
584    /* zlib FAQ: Valgrind (or some similar memory access checker) says that
585       deflate is performing a conditional jump that depends on an
586       uninitialized value.  Isn't that a bug?
587       http://www.zlib.net/zlib_faq.html#faq36 */
588    (void)VALGRIND_MAKE_MEM_DEFINED(p, items * size);
589    return p;
590}
591
592static void
593zlib_mem_free(voidpf opaque, voidpf address)
594{
595    xfree(address);
596}
597
598static void
599zstream_init(struct zstream *z, const struct zstream_funcs *func)
600{
601    z->flags = 0;
602    z->buf = Qnil;
603    z->buf_filled = 0;
604    z->input = Qnil;
605    z->stream.zalloc = zlib_mem_alloc;
606    z->stream.zfree = zlib_mem_free;
607    z->stream.opaque = Z_NULL;
608    z->stream.msg = Z_NULL;
609    z->stream.next_in = Z_NULL;
610    z->stream.avail_in = 0;
611    z->stream.next_out = Z_NULL;
612    z->stream.avail_out = 0;
613    z->func = func;
614}
615
616#define zstream_init_deflate(z)   zstream_init((z), &deflate_funcs)
617#define zstream_init_inflate(z)   zstream_init((z), &inflate_funcs)
618
619static void
620zstream_expand_buffer(struct zstream *z)
621{
622    if (NIL_P(z->buf)) {
623	zstream_expand_buffer_into(z, ZSTREAM_INITIAL_BUFSIZE);
624	return;
625    }
626
627    if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
628	if (z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
629	    int state = 0;
630	    VALUE self = (VALUE)z->stream.opaque;
631
632	    rb_str_resize(z->buf, z->buf_filled);
633	    RBASIC(z->buf)->klass = rb_cString;
634	    OBJ_INFECT(z->buf, self);
635
636	    rb_protect(rb_yield, z->buf, &state);
637
638	    z->buf = Qnil;
639	    zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
640
641	    if (state)
642		rb_jump_tag(state);
643
644	    return;
645	}
646	else {
647	    zstream_expand_buffer_into(z,
648		    ZSTREAM_AVAIL_OUT_STEP_MAX - z->buf_filled);
649	}
650    }
651    else {
652	if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
653	    z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
654	}
655	else {
656	    long inc = z->buf_filled / 2;
657	    if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
658		inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
659	    }
660	    rb_str_resize(z->buf, z->buf_filled + inc);
661	    z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
662		(int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
663	}
664	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
665    }
666}
667
668static void
669zstream_expand_buffer_into(struct zstream *z, unsigned long size)
670{
671    if (NIL_P(z->buf)) {
672	/* I uses rb_str_new here not rb_str_buf_new because
673	   rb_str_buf_new makes a zero-length string. */
674	z->buf = rb_str_new(0, size);
675	z->buf_filled = 0;
676	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
677	z->stream.avail_out = MAX_UINT(size);
678	RBASIC(z->buf)->klass = 0;
679    }
680    else if (z->stream.avail_out != size) {
681	rb_str_resize(z->buf, z->buf_filled + size);
682	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
683	z->stream.avail_out = MAX_UINT(size);
684    }
685}
686
687static void *
688zstream_expand_buffer_protect(void *ptr)
689{
690    struct zstream *z = (struct zstream *)ptr;
691    int state = 0;
692
693    rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
694
695    return (void *)(VALUE)state;
696}
697
698static int
699zstream_expand_buffer_without_gvl(struct zstream *z)
700{
701    char * new_str;
702    long inc, len;
703
704    if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
705	z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
706    }
707    else {
708	inc = z->buf_filled / 2;
709	if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
710	    inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
711	}
712
713	len = z->buf_filled + inc;
714
715	new_str = ruby_xrealloc(RSTRING(z->buf)->as.heap.ptr, len + 1);
716
717	/* from rb_str_resize */
718	RSTRING(z->buf)->as.heap.ptr = new_str;
719	RSTRING(z->buf)->as.heap.ptr[len] = '\0'; /* sentinel */
720	RSTRING(z->buf)->as.heap.len =
721	    RSTRING(z->buf)->as.heap.aux.capa = len;
722
723	z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
724	    (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
725    }
726    z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
727
728    return ZSTREAM_EXPAND_BUFFER_OK;
729}
730
731static void
732zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
733{
734    if (NIL_P(z->buf)) {
735	z->buf = rb_str_buf_new(len);
736	rb_str_buf_cat(z->buf, (const char*)src, len);
737	z->buf_filled = len;
738	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
739	z->stream.avail_out = 0;
740	RBASIC(z->buf)->klass = 0;
741	return;
742    }
743
744    if (RSTRING_LEN(z->buf) < z->buf_filled + len) {
745	rb_str_resize(z->buf, z->buf_filled + len);
746	z->stream.avail_out = 0;
747    }
748    else {
749	if (z->stream.avail_out >= (uInt)len) {
750	    z->stream.avail_out -= (uInt)len;
751	}
752	else {
753	    z->stream.avail_out = 0;
754	}
755    }
756    memcpy(RSTRING_PTR(z->buf) + z->buf_filled, src, len);
757    z->buf_filled += len;
758    z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
759}
760
761#define zstream_append_buffer2(z,v) \
762    zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v))
763
764static VALUE
765zstream_detach_buffer(struct zstream *z)
766{
767    VALUE dst, self = (VALUE)z->stream.opaque;
768
769    if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
770	    rb_block_given_p()) {
771	/* prevent tiny yields mid-stream, save for next
772	 * zstream_expand_buffer() or stream end */
773	return Qnil;
774    }
775
776    if (NIL_P(z->buf)) {
777	dst = rb_str_new(0, 0);
778    }
779    else {
780	dst = z->buf;
781	rb_str_resize(dst, z->buf_filled);
782	RBASIC(dst)->klass = rb_cString;
783    }
784
785    OBJ_INFECT(dst, self);
786
787    z->buf = Qnil;
788    z->buf_filled = 0;
789    z->stream.next_out = 0;
790    z->stream.avail_out = 0;
791
792    if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
793	rb_yield(dst);
794	dst = Qnil;
795    }
796
797    return dst;
798}
799
800static VALUE
801zstream_shift_buffer(struct zstream *z, long len)
802{
803    VALUE dst;
804    long buflen;
805
806    if (z->buf_filled <= len) {
807	return zstream_detach_buffer(z);
808    }
809
810    dst = rb_str_subseq(z->buf, 0, len);
811    RBASIC(dst)->klass = rb_cString;
812    z->buf_filled -= len;
813    memmove(RSTRING_PTR(z->buf), RSTRING_PTR(z->buf) + len,
814	    z->buf_filled);
815    z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
816    buflen = RSTRING_LEN(z->buf) - z->buf_filled;
817    if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
818	buflen = ZSTREAM_AVAIL_OUT_STEP_MAX;
819    }
820    z->stream.avail_out = (uInt)buflen;
821
822    return dst;
823}
824
825static void
826zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
827{
828    if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
829	zstream_expand_buffer_into(z, len);
830    }
831
832    memmove(RSTRING_PTR(z->buf) + len, RSTRING_PTR(z->buf), z->buf_filled);
833    memmove(RSTRING_PTR(z->buf), b, len);
834    z->buf_filled+=len;
835    if (z->stream.avail_out > 0) {
836	if (len > z->stream.avail_out) len = z->stream.avail_out;
837	z->stream.next_out+=len;
838	z->stream.avail_out-=(uInt)len;
839    }
840}
841
842static void
843zstream_buffer_ungetbyte(struct zstream *z, int c)
844{
845    if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
846	zstream_expand_buffer(z);
847    }
848
849    memmove(RSTRING_PTR(z->buf) + 1, RSTRING_PTR(z->buf), z->buf_filled);
850    RSTRING_PTR(z->buf)[0] = (char)c;
851    z->buf_filled++;
852    if (z->stream.avail_out > 0) {
853	z->stream.next_out++;
854	z->stream.avail_out--;
855    }
856}
857
858static void
859zstream_append_input(struct zstream *z, const Bytef *src, long len)
860{
861    if (len <= 0) return;
862
863    if (NIL_P(z->input)) {
864	z->input = rb_str_buf_new(len);
865	rb_str_buf_cat(z->input, (const char*)src, len);
866	RBASIC(z->input)->klass = 0;
867    }
868    else {
869	rb_str_buf_cat(z->input, (const char*)src, len);
870    }
871}
872
873#define zstream_append_input2(z,v)\
874    RB_GC_GUARD(v),\
875    zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
876
877static void
878zstream_discard_input(struct zstream *z, long len)
879{
880    if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) {
881	z->input = Qnil;
882    }
883    else {
884	memmove(RSTRING_PTR(z->input), RSTRING_PTR(z->input) + len,
885		RSTRING_LEN(z->input) - len);
886	rb_str_resize(z->input, RSTRING_LEN(z->input) - len);
887    }
888}
889
890static void
891zstream_reset_input(struct zstream *z)
892{
893    z->input = Qnil;
894}
895
896static void
897zstream_passthrough_input(struct zstream *z)
898{
899    if (!NIL_P(z->input)) {
900	zstream_append_buffer2(z, z->input);
901	z->input = Qnil;
902    }
903}
904
905static VALUE
906zstream_detach_input(struct zstream *z)
907{
908    VALUE dst;
909
910    if (NIL_P(z->input)) {
911	dst = rb_str_new(0, 0);
912    }
913    else {
914	dst = z->input;
915	RBASIC(dst)->klass = rb_cString;
916    }
917    z->input = Qnil;
918    RBASIC(dst)->klass = rb_cString;
919    return dst;
920}
921
922static void
923zstream_reset(struct zstream *z)
924{
925    int err;
926
927    err = z->func->reset(&z->stream);
928    if (err != Z_OK) {
929	raise_zlib_error(err, z->stream.msg);
930    }
931    z->flags = ZSTREAM_FLAG_READY;
932    z->buf = Qnil;
933    z->buf_filled = 0;
934    z->stream.next_out = 0;
935    z->stream.avail_out = 0;
936    zstream_reset_input(z);
937}
938
939static VALUE
940zstream_end(struct zstream *z)
941{
942    int err;
943
944    if (!ZSTREAM_IS_READY(z)) {
945	rb_warning("attempt to close uninitialized zstream; ignored.");
946	return Qnil;
947    }
948    if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
949	rb_warning("attempt to close unfinished zstream; reset forced.");
950	zstream_reset(z);
951    }
952
953    zstream_reset_input(z);
954    err = z->func->end(&z->stream);
955    if (err != Z_OK) {
956	raise_zlib_error(err, z->stream.msg);
957    }
958    z->flags = 0;
959    return Qnil;
960}
961
962static void *
963zstream_run_func(void *ptr)
964{
965    struct zstream_run_args *args = (struct zstream_run_args *)ptr;
966    int err, state, flush = args->flush;
967    struct zstream *z = args->z;
968    uInt n;
969
970    err = Z_OK;
971    while (!args->interrupt) {
972	n = z->stream.avail_out;
973	err = z->func->run(&z->stream, flush);
974	z->buf_filled += n - z->stream.avail_out;
975
976	if (err == Z_STREAM_END) {
977	    z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
978	    z->flags |= ZSTREAM_FLAG_FINISHED;
979	    break;
980	}
981
982	if (err != Z_OK && err != Z_BUF_ERROR)
983	    break;
984
985	if (z->stream.avail_out > 0) {
986	    z->flags |= ZSTREAM_FLAG_IN_STREAM;
987	    break;
988	}
989
990	if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
991	    /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
992	    /* but deflate() could be called with avail_in == 0 (there's hidden buffer
993	       in zstream->state) */
994	    z->flags |= ZSTREAM_FLAG_IN_STREAM;
995	    break;
996	}
997
998	if (args->stream_output) {
999	    state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
1000							(void *)z);
1001	} else {
1002	    state = zstream_expand_buffer_without_gvl(z);
1003	}
1004
1005	if (state) {
1006	    err = Z_OK; /* buffer expanded but stream processing was stopped */
1007	    args->jump_state = state;
1008	    break;
1009	}
1010    }
1011
1012    return (void *)(VALUE)err;
1013}
1014
1015/*
1016 * There is no safe way to interrupt z->run->func().
1017 */
1018static void
1019zstream_unblock_func(void *ptr)
1020{
1021    struct zstream_run_args *args = (struct zstream_run_args *)ptr;
1022
1023    args->interrupt = 1;
1024}
1025
1026static void
1027zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1028{
1029    struct zstream_run_args args;
1030    int err;
1031    volatile VALUE guard = Qnil;
1032
1033    args.z = z;
1034    args.flush = flush;
1035    args.interrupt = 0;
1036    args.jump_state = 0;
1037    args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
1038
1039    if (NIL_P(z->input) && len == 0) {
1040	z->stream.next_in = (Bytef*)"";
1041	z->stream.avail_in = 0;
1042    }
1043    else {
1044	zstream_append_input(z, src, len);
1045	z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1046	z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1047	/* keep reference to `z->input' so as not to be garbage collected
1048	   after zstream_reset_input() and prevent `z->stream.next_in'
1049	   from dangling. */
1050	guard = z->input;
1051    }
1052
1053    if (z->stream.avail_out == 0) {
1054	zstream_expand_buffer(z);
1055    }
1056
1057loop:
1058    err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
1059						 zstream_unblock_func, (void *)&args);
1060
1061    if (flush != Z_FINISH && err == Z_BUF_ERROR
1062	    && z->stream.avail_out > 0) {
1063	z->flags |= ZSTREAM_FLAG_IN_STREAM;
1064    }
1065
1066    zstream_reset_input(z);
1067
1068    if (err != Z_OK && err != Z_STREAM_END) {
1069	if (z->stream.avail_in > 0) {
1070	    zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1071	}
1072	if (err == Z_NEED_DICT) {
1073	    VALUE self = (VALUE)z->stream.opaque;
1074	    if (self) {
1075		VALUE dicts = rb_ivar_get(self, id_dictionaries);
1076		VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
1077		if (!NIL_P(dict)) {
1078		    rb_inflate_set_dictionary(self, dict);
1079		    goto loop;
1080		}
1081	    }
1082	}
1083	raise_zlib_error(err, z->stream.msg);
1084    }
1085
1086    if (z->stream.avail_in > 0) {
1087	zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1088        RB_GC_GUARD(guard) = Qnil; /* prevent tail call to make guard effective */
1089    }
1090
1091    if (args.jump_state)
1092	rb_jump_tag(args.jump_state);
1093}
1094
1095static VALUE
1096zstream_sync(struct zstream *z, Bytef *src, long len)
1097{
1098    /* VALUE rest; */
1099    int err;
1100
1101    if (!NIL_P(z->input)) {
1102	z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1103	z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1104	err = inflateSync(&z->stream);
1105	if (err == Z_OK) {
1106	    zstream_discard_input(z,
1107				  RSTRING_LEN(z->input) - z->stream.avail_in);
1108	    zstream_append_input(z, src, len);
1109	    return Qtrue;
1110	}
1111	zstream_reset_input(z);
1112	if (err != Z_DATA_ERROR) {
1113	    /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1114	    raise_zlib_error(err, z->stream.msg);
1115	}
1116    }
1117
1118    if (len <= 0) return Qfalse;
1119
1120    z->stream.next_in = src;
1121    z->stream.avail_in = MAX_UINT(len);
1122    err = inflateSync(&z->stream);
1123    if (err == Z_OK) {
1124	zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1125	return Qtrue;
1126    }
1127    if (err != Z_DATA_ERROR) {
1128	/* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1129	raise_zlib_error(err, z->stream.msg);
1130    }
1131    return Qfalse;
1132}
1133
1134static void
1135zstream_mark(struct zstream *z)
1136{
1137    rb_gc_mark(z->buf);
1138    rb_gc_mark(z->input);
1139}
1140
1141static void
1142zstream_finalize(struct zstream *z)
1143{
1144    int err = z->func->end(&z->stream);
1145    if (err == Z_STREAM_ERROR)
1146	finalizer_warn("the stream state was inconsistent.");
1147    if (err == Z_DATA_ERROR)
1148	finalizer_warn("the stream was freed prematurely.");
1149}
1150
1151static void
1152zstream_free(struct zstream *z)
1153{
1154    if (ZSTREAM_IS_READY(z)) {
1155	zstream_finalize(z);
1156    }
1157    xfree(z);
1158}
1159
1160static VALUE
1161zstream_new(VALUE klass, const struct zstream_funcs *funcs)
1162{
1163    VALUE obj;
1164    struct zstream *z;
1165
1166    obj = Data_Make_Struct(klass, struct zstream,
1167			   zstream_mark, zstream_free, z);
1168    zstream_init(z, funcs);
1169    z->stream.opaque = (voidpf)obj;
1170    return obj;
1171}
1172
1173#define zstream_deflate_new(klass)  zstream_new((klass), &deflate_funcs)
1174#define zstream_inflate_new(klass)  zstream_new((klass), &inflate_funcs)
1175
1176static struct zstream *
1177get_zstream(VALUE obj)
1178{
1179    struct zstream *z;
1180
1181    Data_Get_Struct(obj, struct zstream, z);
1182    if (!ZSTREAM_IS_READY(z)) {
1183	rb_raise(cZError, "stream is not ready");
1184    }
1185    return z;
1186}
1187
1188
1189/* ------------------------------------------------------------------------- */
1190
1191/*
1192 * Document-class: Zlib::ZStream
1193 *
1194 * Zlib::ZStream is the abstract class for the stream which handles the
1195 * compressed data. The operations are defined in the subclasses:
1196 * Zlib::Deflate for compression, and Zlib::Inflate for decompression.
1197 *
1198 * An instance of Zlib::ZStream has one stream (struct zstream in the source)
1199 * and two variable-length buffers which associated to the input (next_in) of
1200 * the stream and the output (next_out) of the stream. In this document,
1201 * "input buffer" means the buffer for input, and "output buffer" means the
1202 * buffer for output.
1203 *
1204 * Data input into an instance of Zlib::ZStream are temporally stored into
1205 * the end of input buffer, and then data in input buffer are processed from
1206 * the beginning of the buffer until no more output from the stream is
1207 * produced (i.e. until avail_out > 0 after processing).  During processing,
1208 * output buffer is allocated and expanded automatically to hold all output
1209 * data.
1210 *
1211 * Some particular instance methods consume the data in output buffer and
1212 * return them as a String.
1213 *
1214 * Here is an ascii art for describing above:
1215 *
1216 *    +================ an instance of Zlib::ZStream ================+
1217 *    ||                                                            ||
1218 *    ||     +--------+          +-------+          +--------+      ||
1219 *    ||  +--| output |<---------|zstream|<---------| input  |<--+  ||
1220 *    ||  |  | buffer |  next_out+-------+next_in   | buffer |   |  ||
1221 *    ||  |  +--------+                             +--------+   |  ||
1222 *    ||  |                                                      |  ||
1223 *    +===|======================================================|===+
1224 *        |                                                      |
1225 *        v                                                      |
1226 *    "output data"                                         "input data"
1227 *
1228 * If an error occurs during processing input buffer, an exception which is a
1229 * subclass of Zlib::Error is raised.  At that time, both input and output
1230 * buffer keep their conditions at the time when the error occurs.
1231 *
1232 * == Method Catalogue
1233 *
1234 * Many of the methods in this class are fairly low-level and unlikely to be
1235 * of interest to users.  In fact, users are unlikely to use this class
1236 * directly; rather they will be interested in Zlib::Inflate and
1237 * Zlib::Deflate.
1238 *
1239 * The higher level methods are listed below.
1240 *
1241 * - #total_in
1242 * - #total_out
1243 * - #data_type
1244 * - #adler
1245 * - #reset
1246 * - #finish
1247 * - #finished?
1248 * - #close
1249 * - #closed?
1250 */
1251
1252/*
1253 * Closes the stream. All operations on the closed stream will raise an
1254 * exception.
1255 */
1256static VALUE
1257rb_zstream_end(VALUE obj)
1258{
1259    zstream_end(get_zstream(obj));
1260    return Qnil;
1261}
1262
1263/*
1264 * Resets and initializes the stream. All data in both input and output buffer
1265 * are discarded.
1266 */
1267static VALUE
1268rb_zstream_reset(VALUE obj)
1269{
1270    zstream_reset(get_zstream(obj));
1271    return Qnil;
1272}
1273
1274/*
1275 * call-seq:
1276 *   finish                 -> String
1277 *   finish { |chunk| ... } -> nil
1278 *
1279 * Finishes the stream and flushes output buffer.  If a block is given each
1280 * chunk is yielded to the block until the input buffer has been flushed to
1281 * the output buffer.
1282 */
1283static VALUE
1284rb_zstream_finish(VALUE obj)
1285{
1286    struct zstream *z = get_zstream(obj);
1287
1288    zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1289
1290    return zstream_detach_buffer(z);
1291}
1292
1293/*
1294 * call-seq:
1295 *   flush_next_out                 -> String
1296 *   flush_next_out { |chunk| ... } -> nil
1297 *
1298 * Flushes output buffer and returns all data in that buffer.  If a block is
1299 * given each chunk is yielded to the block until the current output buffer
1300 * has been flushed.
1301 */
1302static VALUE
1303rb_zstream_flush_next_in(VALUE obj)
1304{
1305    struct zstream *z;
1306    VALUE dst;
1307
1308    Data_Get_Struct(obj, struct zstream, z);
1309    dst = zstream_detach_input(z);
1310    OBJ_INFECT(dst, obj);
1311    return dst;
1312}
1313
1314/*
1315 * Flushes output buffer and returns all data in that buffer.
1316 */
1317static VALUE
1318rb_zstream_flush_next_out(VALUE obj)
1319{
1320    struct zstream *z;
1321
1322    Data_Get_Struct(obj, struct zstream, z);
1323
1324    return zstream_detach_buffer(z);
1325}
1326
1327/*
1328 * Returns number of bytes of free spaces in output buffer.  Because the free
1329 * space is allocated automatically, this method returns 0 normally.
1330 */
1331static VALUE
1332rb_zstream_avail_out(VALUE obj)
1333{
1334    struct zstream *z;
1335    Data_Get_Struct(obj, struct zstream, z);
1336    return rb_uint2inum(z->stream.avail_out);
1337}
1338
1339/*
1340 * Allocates +size+ bytes of free space in the output buffer. If there are more
1341 * than +size+ bytes already in the buffer, the buffer is truncated. Because
1342 * free space is allocated automatically, you usually don't need to use this
1343 * method.
1344 */
1345static VALUE
1346rb_zstream_set_avail_out(VALUE obj, VALUE size)
1347{
1348    struct zstream *z = get_zstream(obj);
1349
1350    Check_Type(size, T_FIXNUM);
1351    zstream_expand_buffer_into(z, FIX2INT(size));
1352    return size;
1353}
1354
1355/*
1356 * Returns bytes of data in the input buffer. Normally, returns 0.
1357 */
1358static VALUE
1359rb_zstream_avail_in(VALUE obj)
1360{
1361    struct zstream *z;
1362    Data_Get_Struct(obj, struct zstream, z);
1363    return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING_LEN(z->input)));
1364}
1365
1366/*
1367 * Returns the total bytes of the input data to the stream.  FIXME
1368 */
1369static VALUE
1370rb_zstream_total_in(VALUE obj)
1371{
1372    return rb_uint2inum(get_zstream(obj)->stream.total_in);
1373}
1374
1375/*
1376 * Returns the total bytes of the output data from the stream.  FIXME
1377 */
1378static VALUE
1379rb_zstream_total_out(VALUE obj)
1380{
1381    return rb_uint2inum(get_zstream(obj)->stream.total_out);
1382}
1383
1384/*
1385 * Guesses the type of the data which have been inputed into the stream. The
1386 * returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
1387 * <tt>UNKNOWN</tt>.
1388 */
1389static VALUE
1390rb_zstream_data_type(VALUE obj)
1391{
1392    return INT2FIX(get_zstream(obj)->stream.data_type);
1393}
1394
1395/*
1396 * Returns the adler-32 checksum.
1397 */
1398static VALUE
1399rb_zstream_adler(VALUE obj)
1400{
1401	return rb_uint2inum(get_zstream(obj)->stream.adler);
1402}
1403
1404/*
1405 * Returns true if the stream is finished.
1406 */
1407static VALUE
1408rb_zstream_finished_p(VALUE obj)
1409{
1410    return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
1411}
1412
1413/*
1414 * Returns true if the stream is closed.
1415 */
1416static VALUE
1417rb_zstream_closed_p(VALUE obj)
1418{
1419    struct zstream *z;
1420    Data_Get_Struct(obj, struct zstream, z);
1421    return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
1422}
1423
1424
1425/* ------------------------------------------------------------------------- */
1426
1427/*
1428 * Document-class: Zlib::Deflate
1429 *
1430 * Zlib::Deflate is the class for compressing data.  See Zlib::ZStream for more
1431 * information.
1432 */
1433
1434#define FIXNUMARG(val, ifnil) \
1435    (NIL_P((val)) ? (ifnil) \
1436    : ((void)Check_Type((val), T_FIXNUM), FIX2INT((val))))
1437
1438#define ARG_LEVEL(val)     FIXNUMARG((val), Z_DEFAULT_COMPRESSION)
1439#define ARG_WBITS(val)     FIXNUMARG((val), MAX_WBITS)
1440#define ARG_MEMLEVEL(val)  FIXNUMARG((val), DEF_MEM_LEVEL)
1441#define ARG_STRATEGY(val)  FIXNUMARG((val), Z_DEFAULT_STRATEGY)
1442#define ARG_FLUSH(val)     FIXNUMARG((val), Z_NO_FLUSH)
1443
1444
1445static VALUE
1446rb_deflate_s_allocate(VALUE klass)
1447{
1448    return zstream_deflate_new(klass);
1449}
1450
1451/*
1452 * Document-method: Zlib::Deflate.new
1453 *
1454 * call-seq:
1455 *   Zlib::Deflate.new(level=DEFAULT_COMPRESSION, window_bits=MAX_WBITS, mem_level=DEF_MEM_LEVEL, strategy=DEFAULT_STRATEGY)
1456 *
1457 * Creates a new deflate stream for compression. If a given argument is nil,
1458 * the default value of that argument is used.
1459 *
1460 * The +level+ sets the compression level for the deflate stream between 0 (no
1461 * compression) and 9 (best compression. The following constants have been
1462 * defined to make code more readable:
1463 *
1464 * * Zlib::NO_COMPRESSION = 0
1465 * * Zlib::BEST_SPEED = 1
1466 * * Zlib::DEFAULT_COMPRESSION = 6
1467 * * Zlib::BEST_COMPRESSION = 9
1468 *
1469 * The +window_bits+ sets the size of the history buffer and should be between
1470 * 8 and 15.  Larger values of this parameter result in better compression at
1471 * the expense of memory usage.
1472 *
1473 * The +mem_level+ specifies how much memory should be allocated for the
1474 * internal compression state.  1 uses minimum memory but is slow and reduces
1475 * compression ratio while 9 uses maximum memory for optimal speed.  The
1476 * default value is 8. Two constants are defined:
1477 *
1478 * * Zlib::DEF_MEM_LEVEL
1479 * * Zlib::MAX_MEM_LEVEL
1480 *
1481 * The +strategy+ sets the deflate compression strategy.  The following
1482 * strategies are available:
1483 *
1484 * Zlib::DEFAULT_STRATEGY:: For normal data
1485 * Zlib::FILTERED:: For data produced by a filter or predictor
1486 * Zlib::FIXED:: Prevents dynamic Huffman codes
1487 * Zlib::HUFFMAN_ONLY:: Prevents string matching
1488 * Zlib::RLE:: Designed for better compression of PNG image data
1489 *
1490 * See the constants for further description.
1491 *
1492 * == Examples
1493 *
1494 * === Basic
1495 *
1496 *   open "compressed.file", "w+" do |io|
1497 *     io << Zlib::Deflate.new.deflate(File.read("big.file"))
1498 *   end
1499 *
1500 * === Custom compression
1501 *
1502 *   open "compressed.file", "w+" do |compressed_io|
1503 *     deflate = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
1504 *                                 Zlib::MAX_WBITS,
1505 *                                 Zlib::MAX_MEM_LEVEL,
1506 *                                 Zlib::HUFFMAN_ONLY)
1507 *
1508 *     begin
1509 *       open "big.file" do |big_io|
1510 *         until big_io.eof? do
1511 *           compressed_io << zd.deflate(big_io.read(16384))
1512 *         end
1513 *       end
1514 *     ensure
1515 *       deflate.close
1516 *     end
1517 *   end
1518 *
1519 * While this example will work, for best optimization review the flags for
1520 * your specific time, memory usage and output space requirements.
1521 */
1522static VALUE
1523rb_deflate_initialize(int argc, VALUE *argv, VALUE obj)
1524{
1525    struct zstream *z;
1526    VALUE level, wbits, memlevel, strategy;
1527    int err;
1528
1529    rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
1530    Data_Get_Struct(obj, struct zstream, z);
1531
1532    err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
1533		       ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
1534		       ARG_STRATEGY(strategy));
1535    if (err != Z_OK) {
1536	raise_zlib_error(err, z->stream.msg);
1537    }
1538    ZSTREAM_READY(z);
1539
1540    return obj;
1541}
1542
1543/*
1544 * Document-method: Zlib::Deflate#initialize_copy
1545 *
1546 * Duplicates the deflate stream.
1547 */
1548static VALUE
1549rb_deflate_init_copy(VALUE self, VALUE orig)
1550{
1551    struct zstream *z1, *z2;
1552    int err;
1553
1554    Data_Get_Struct(self, struct zstream, z1);
1555    z2 = get_zstream(orig);
1556
1557    if (z1 == z2) return self;
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
1570static VALUE
1571deflate_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 */
1603static VALUE
1604rb_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
1629static void
1630do_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 */
1668static VALUE
1669rb_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 */
1690static VALUE
1691rb_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 */
1713static VALUE
1714rb_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 */
1741static VALUE
1742rb_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 */
1783static VALUE
1784rb_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
1812static VALUE
1813rb_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 */
1865static VALUE
1866rb_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
1884static VALUE
1885inflate_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 */
1918static VALUE
1919rb_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
1941static void
1942do_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 */
1963static VALUE
1964rb_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 */
2010static VALUE
2011rb_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 */
2047static VALUE
2048rb_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 */
2078static VALUE
2079rb_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 */
2095static VALUE
2096rb_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 */
2118static VALUE
2119rb_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
2182static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
2183static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
2184
2185
2186
2187/*-------- gzfile internal APIs --------*/
2188
2189struct 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
2221static void
2222gzfile_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
2232static void
2233gzfile_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
2249static VALUE
2250gzfile_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
2285static void
2286gzfile_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
2299static void
2300gzfile_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
2313static void
2314gzfile_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
2328static VALUE
2329gzfile_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
2339static VALUE
2340gzfile_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
2353static VALUE
2354gzfile_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
2361static int
2362gzfile_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
2374static char *
2375gzfile_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
2394static unsigned int
2395gzfile_get16(const unsigned char *src)
2396{
2397    unsigned int n;
2398    n  = *(src++) & 0xff;
2399    n |= (*(src++) & 0xff) << 8;
2400    return n;
2401}
2402
2403static unsigned long
2404gzfile_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
2414static void
2415gzfile_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
2423static void
2424gzfile_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 */
2438static VALUE
2439gzfile_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
2453static void
2454gzfile_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
2497static void
2498gzfile_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
2508static void
2509gzfile_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
2589static void
2590gzfile_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
2614static void
2615gzfile_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
2629static long
2630gzfile_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
2651static void
2652gzfile_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
2664static VALUE
2665gzfile_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
2682static long
2683gzfile_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
2701static VALUE
2702gzfile_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
2714static VALUE
2715gzfile_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
2757static VALUE
2758gzfile_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
2779static VALUE
2780gzfile_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
2825static void
2826gzfile_ungets(struct gzfile *gz, const Bytef *b, long len)
2827{
2828    zstream_buffer_ungets(&gz->z, b, len);
2829    gz->ungetc+=len;
2830}
2831
2832static void
2833gzfile_ungetbyte(struct gzfile *gz, int c)
2834{
2835    zstream_buffer_ungetbyte(&gz->z, c);
2836    gz->ungetc++;
2837}
2838
2839static VALUE
2840gzfile_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
2855static void
2856gzfile_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
2864static VALUE
2865gzfile_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
2877static void
2878gzfile_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
2886static void
2887gzfile_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
2900static VALUE
2901gzfile_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
2917static struct gzfile *
2918get_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
2970typedef struct {
2971    int argc;
2972    VALUE *argv;
2973    VALUE klass;
2974} new_wrap_arg_t;
2975
2976static VALUE
2977new_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
2983static VALUE
2984gzfile_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
2995static VALUE
2996gzfile_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 */
3039static VALUE
3040rb_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 */
3050static VALUE
3051gzfile_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 */
3069static VALUE
3070rb_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 */
3080static VALUE
3081rb_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 */
3091static VALUE
3092rb_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 */
3102static VALUE
3103rb_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 */
3113static VALUE
3114rb_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 */
3125static VALUE
3126rb_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 */
3142static VALUE
3143rb_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 */
3158static VALUE
3159rb_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 */
3169static VALUE
3170rb_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 */
3183static VALUE
3184rb_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 */
3208static VALUE
3209rb_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 */
3232static VALUE
3233rb_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 */
3257static VALUE
3258rb_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 */
3275static VALUE
3276rb_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 */
3292static VALUE
3293rb_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 */
3305static VALUE
3306rb_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 */
3318static VALUE
3319rb_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 */
3333static VALUE
3334rb_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 */
3352static VALUE
3353rb_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 */
3363static VALUE
3364rb_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 */
3378static VALUE
3379rb_gzfile_path(VALUE obj)
3380{
3381    struct gzfile *gz;
3382    Data_Get_Struct(obj, struct gzfile, gz);
3383    return gz->path;
3384}
3385
3386static void
3387rb_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
3435static VALUE
3436rb_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 */
3448static VALUE
3449rb_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 */
3467static VALUE
3468rb_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 */
3508static VALUE
3509rb_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 */
3532static VALUE
3533rb_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 */
3549static VALUE
3550rb_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
3637static VALUE
3638rb_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 */
3652static VALUE
3653rb_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 */
3675static VALUE
3676rb_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 */
3709static VALUE
3710rb_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 */
3723static VALUE
3724rb_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 */
3736static VALUE
3737rb_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 */
3767static VALUE
3768rb_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 */
3790static VALUE
3791rb_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 */
3803static VALUE
3804rb_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 */
3819static VALUE
3820rb_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 */
3837static VALUE
3838rb_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 */
3853static VALUE
3854rb_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 */
3871static VALUE
3872rb_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 */
3889static VALUE
3890rb_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 */
3903static VALUE
3904rb_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 */
3924static VALUE
3925rb_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
3932static void
3933gzreader_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
3963static void
3964rscheck(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
3970static long
3971gzreader_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
3991static VALUE
3992gzreader_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 */
4121static VALUE
4122rb_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 */
4137static VALUE
4138rb_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 */
4153static VALUE
4154rb_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 */
4171static VALUE
4172rb_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 */
4185static VALUE
4186rb_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
4198void
4199Init_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