Ruby  2.0.0p353(2013-11-22revision43784)
ext/zlib/zlib.c
Go to the documentation of this file.
00001 /*
00002  * zlib.c - An interface for zlib.
00003  *
00004  *   Copyright (C) UENO Katsuhiro 2000-2003
00005  *
00006  * $Id: zlib.c 42727 2013-08-29 12:55:11Z nagachika $
00007  */
00008 
00009 #include <ruby.h>
00010 #include <zlib.h>
00011 #include <time.h>
00012 #include <ruby/io.h>
00013 #include <ruby/thread.h>
00014 
00015 #ifdef HAVE_VALGRIND_MEMCHECK_H
00016 # include <valgrind/memcheck.h>
00017 # ifndef VALGRIND_MAKE_MEM_DEFINED
00018 #  define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
00019 # endif
00020 # ifndef VALGRIND_MAKE_MEM_UNDEFINED
00021 #  define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
00022 # endif
00023 #else
00024 # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
00025 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
00026 #endif
00027 
00028 #define RUBY_ZLIB_VERSION  "0.6.0"
00029 
00030 
00031 #define OBJ_IS_FREED(val)  (RBASIC(val)->flags == 0)
00032 
00033 #ifndef GZIP_SUPPORT
00034 #define GZIP_SUPPORT  1
00035 #endif
00036 
00037 /* from zutil.h */
00038 #ifndef DEF_MEM_LEVEL
00039 #if MAX_MEM_LEVEL >= 8
00040 #define DEF_MEM_LEVEL  8
00041 #else
00042 #define DEF_MEM_LEVEL  MAX_MEM_LEVEL
00043 #endif
00044 #endif
00045 
00046 #if SIZEOF_LONG > SIZEOF_INT
00047 static inline uInt
00048 max_uint(long n)
00049 {
00050     if (n > UINT_MAX) n = UINT_MAX;
00051     return (uInt)n;
00052 }
00053 #define MAX_UINT(n) max_uint(n)
00054 #else
00055 #define MAX_UINT(n) (uInt)(n)
00056 #endif
00057 
00058 #define sizeof(x) ((int)sizeof(x))
00059 
00060 static ID id_dictionaries;
00061 
00062 /*--------- Prototypes --------*/
00063 
00064 static NORETURN(void raise_zlib_error(int, const char*));
00065 static VALUE rb_zlib_version(VALUE);
00066 static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
00067 static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
00068 static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
00069 static VALUE rb_zlib_crc_table(VALUE);
00070 static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
00071 static void zlib_mem_free(voidpf, voidpf);
00072 static void finalizer_warn(const char*);
00073 
00074 struct zstream;
00075 struct zstream_funcs;
00076 struct zstream_run_args;
00077 static void zstream_init(struct zstream*, const struct zstream_funcs*);
00078 static void zstream_expand_buffer(struct zstream*);
00079 static void zstream_expand_buffer_into(struct zstream*, unsigned long);
00080 static void zstream_append_buffer(struct zstream*, const Bytef*, long);
00081 static VALUE zstream_detach_buffer(struct zstream*);
00082 static VALUE zstream_shift_buffer(struct zstream*, long);
00083 static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
00084 static void zstream_buffer_ungetbyte(struct zstream*, int);
00085 static void zstream_append_input(struct zstream*, const Bytef*, long);
00086 static void zstream_discard_input(struct zstream*, long);
00087 static void zstream_reset_input(struct zstream*);
00088 static void zstream_passthrough_input(struct zstream*);
00089 static VALUE zstream_detach_input(struct zstream*);
00090 static void zstream_reset(struct zstream*);
00091 static VALUE zstream_end(struct zstream*);
00092 static void zstream_run(struct zstream*, Bytef*, long, int);
00093 static VALUE zstream_sync(struct zstream*, Bytef*, long);
00094 static void zstream_mark(struct zstream*);
00095 static void zstream_free(struct zstream*);
00096 static VALUE zstream_new(VALUE, const struct zstream_funcs*);
00097 static struct zstream *get_zstream(VALUE);
00098 static void zstream_finalize(struct zstream*);
00099 
00100 static VALUE rb_zstream_end(VALUE);
00101 static VALUE rb_zstream_reset(VALUE);
00102 static VALUE rb_zstream_finish(VALUE);
00103 static VALUE rb_zstream_flush_next_in(VALUE);
00104 static VALUE rb_zstream_flush_next_out(VALUE);
00105 static VALUE rb_zstream_avail_out(VALUE);
00106 static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
00107 static VALUE rb_zstream_avail_in(VALUE);
00108 static VALUE rb_zstream_total_in(VALUE);
00109 static VALUE rb_zstream_total_out(VALUE);
00110 static VALUE rb_zstream_data_type(VALUE);
00111 static VALUE rb_zstream_adler(VALUE);
00112 static VALUE rb_zstream_finished_p(VALUE);
00113 static VALUE rb_zstream_closed_p(VALUE);
00114 
00115 static VALUE rb_deflate_s_allocate(VALUE);
00116 static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
00117 static VALUE rb_deflate_init_copy(VALUE, VALUE);
00118 static VALUE deflate_run(VALUE);
00119 static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
00120 static void do_deflate(struct zstream*, VALUE, int);
00121 static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
00122 static VALUE rb_deflate_addstr(VALUE, VALUE);
00123 static VALUE rb_deflate_flush(int, VALUE*, VALUE);
00124 static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
00125 static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
00126 
00127 static VALUE inflate_run(VALUE);
00128 static VALUE rb_inflate_s_allocate(VALUE);
00129 static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
00130 static VALUE rb_inflate_s_inflate(VALUE, VALUE);
00131 static void do_inflate(struct zstream*, VALUE);
00132 static VALUE rb_inflate_inflate(VALUE, VALUE);
00133 static VALUE rb_inflate_addstr(VALUE, VALUE);
00134 static VALUE rb_inflate_sync(VALUE, VALUE);
00135 static VALUE rb_inflate_sync_point_p(VALUE);
00136 static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
00137 
00138 #if GZIP_SUPPORT
00139 struct gzfile;
00140 static void gzfile_mark(struct gzfile*);
00141 static void gzfile_free(struct gzfile*);
00142 static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
00143 static void gzfile_reset(struct gzfile*);
00144 static void gzfile_close(struct gzfile*, int);
00145 static void gzfile_write_raw(struct gzfile*);
00146 static VALUE gzfile_read_raw_partial(VALUE);
00147 static VALUE gzfile_read_raw_rescue(VALUE);
00148 static VALUE gzfile_read_raw(struct gzfile*);
00149 static int gzfile_read_raw_ensure(struct gzfile*, long);
00150 static char *gzfile_read_raw_until_zero(struct gzfile*, long);
00151 static unsigned int gzfile_get16(const unsigned char*);
00152 static unsigned long gzfile_get32(const unsigned char*);
00153 static void gzfile_set32(unsigned long n, unsigned char*);
00154 static void gzfile_make_header(struct gzfile*);
00155 static void gzfile_make_footer(struct gzfile*);
00156 static void gzfile_read_header(struct gzfile*);
00157 static void gzfile_check_footer(struct gzfile*);
00158 static void gzfile_write(struct gzfile*, Bytef*, long);
00159 static long gzfile_read_more(struct gzfile*);
00160 static void gzfile_calc_crc(struct gzfile*, VALUE);
00161 static VALUE gzfile_read(struct gzfile*, long);
00162 static VALUE gzfile_read_all(struct gzfile*);
00163 static void gzfile_ungets(struct gzfile*, const Bytef*, long);
00164 static void gzfile_ungetbyte(struct gzfile*, int);
00165 static VALUE gzfile_writer_end_run(VALUE);
00166 static void gzfile_writer_end(struct gzfile*);
00167 static VALUE gzfile_reader_end_run(VALUE);
00168 static void gzfile_reader_end(struct gzfile*);
00169 static void gzfile_reader_rewind(struct gzfile*);
00170 static VALUE gzfile_reader_get_unused(struct gzfile*);
00171 static struct gzfile *get_gzfile(VALUE);
00172 static VALUE gzfile_ensure_close(VALUE);
00173 static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
00174 static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
00175 NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *));
00176 static VALUE gzfile_error_inspect(VALUE);
00177 
00178 static VALUE rb_gzfile_to_io(VALUE);
00179 static VALUE rb_gzfile_crc(VALUE);
00180 static VALUE rb_gzfile_mtime(VALUE);
00181 static VALUE rb_gzfile_level(VALUE);
00182 static VALUE rb_gzfile_os_code(VALUE);
00183 static VALUE rb_gzfile_orig_name(VALUE);
00184 static VALUE rb_gzfile_comment(VALUE);
00185 static VALUE rb_gzfile_lineno(VALUE);
00186 static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
00187 static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
00188 static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
00189 static VALUE rb_gzfile_set_comment(VALUE, VALUE);
00190 static VALUE rb_gzfile_close(VALUE);
00191 static VALUE rb_gzfile_finish(VALUE);
00192 static VALUE rb_gzfile_closed_p(VALUE);
00193 static VALUE rb_gzfile_eof_p(VALUE);
00194 static VALUE rb_gzfile_sync(VALUE);
00195 static VALUE rb_gzfile_set_sync(VALUE, VALUE);
00196 static VALUE rb_gzfile_total_in(VALUE);
00197 static VALUE rb_gzfile_total_out(VALUE);
00198 static VALUE rb_gzfile_path(VALUE);
00199 
00200 static VALUE rb_gzwriter_s_allocate(VALUE);
00201 static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
00202 static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
00203 static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
00204 static VALUE rb_gzwriter_write(VALUE, VALUE);
00205 static VALUE rb_gzwriter_putc(VALUE, VALUE);
00206 
00207 static VALUE rb_gzreader_s_allocate(VALUE);
00208 static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
00209 static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
00210 static VALUE rb_gzreader_rewind(VALUE);
00211 static VALUE rb_gzreader_unused(VALUE);
00212 static VALUE rb_gzreader_read(int, VALUE*, VALUE);
00213 static VALUE rb_gzreader_getc(VALUE);
00214 static VALUE rb_gzreader_readchar(VALUE);
00215 static VALUE rb_gzreader_each_byte(VALUE);
00216 static VALUE rb_gzreader_ungetc(VALUE, VALUE);
00217 static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
00218 static void gzreader_skip_linebreaks(struct gzfile*);
00219 static VALUE gzreader_gets(int, VALUE*, VALUE);
00220 static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
00221 static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
00222 static VALUE rb_gzreader_each(int, VALUE*, VALUE);
00223 static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
00224 #endif /* GZIP_SUPPORT */
00225 
00226 /*
00227  * Document-module: Zlib
00228  *
00229  * This module provides access to the {zlib library}[http://zlib.net]. Zlib is
00230  * designed to be a portable, free, general-purpose, legally unencumbered --
00231  * that is, not covered by any patents -- lossless data-compression library
00232  * for use on virtually any computer hardware and operating system.
00233  *
00234  * The zlib compression library provides in-memory compression and
00235  * decompression functions, including integrity checks of the uncompressed
00236  * data.
00237  *
00238  * The zlib compressed data format is described in RFC 1950, which is a
00239  * wrapper around a deflate stream which is described in RFC 1951.
00240  *
00241  * The library also supports reading and writing files in gzip (.gz) format
00242  * with an interface similar to that of IO. The gzip format is described in
00243  * RFC 1952 which is also a wrapper around a deflate stream.
00244  *
00245  * The zlib format was designed to be compact and fast for use in memory and on
00246  * communications channels. The gzip format was designed for single-file
00247  * compression on file systems, has a larger header than zlib to maintain
00248  * directory information, and uses a different, slower check method than zlib.
00249  *
00250  * See your system's zlib.h for further information about zlib
00251  *
00252  * == Sample usage
00253  *
00254  * Using the wrapper to compress strings with default parameters is quite
00255  * simple:
00256  *
00257  *   require "zlib"
00258  *
00259  *   data_to_compress = File.read("don_quixote.txt")
00260  *
00261  *   puts "Input size: #{data_to_compress.size}"
00262  *   #=> Input size: 2347740
00263  *
00264  *   data_compressed = Zlib::Deflate.deflate(data_to_compress)
00265  *
00266  *   puts "Compressed size: #{data_compressed.size}"
00267  *   #=> Compressed size: 887238
00268  *
00269  *   uncompressed_data = Zlib::Inflate.inflate(data_compressed)
00270  *
00271  *   puts "Uncompressed data is: #{uncompressed_data}"
00272  *   #=> Uncompressed data is: The Project Gutenberg EBook of Don Quixote...
00273  *
00274  * == Class tree
00275  *
00276  * - Zlib::Deflate
00277  * - Zlib::Inflate
00278  * - Zlib::ZStream
00279  * - Zlib::Error
00280  *   - Zlib::StreamEnd
00281  *   - Zlib::NeedDict
00282  *   - Zlib::DataError
00283  *   - Zlib::StreamError
00284  *   - Zlib::MemError
00285  *   - Zlib::BufError
00286  *   - Zlib::VersionError
00287  *
00288  * (if you have GZIP_SUPPORT)
00289  * - Zlib::GzipReader
00290  * - Zlib::GzipWriter
00291  * - Zlib::GzipFile
00292  * - Zlib::GzipFile::Error
00293  *   - Zlib::GzipFile::LengthError
00294  *   - Zlib::GzipFile::CRCError
00295  *   - Zlib::GzipFile::NoFooter
00296  *
00297  */
00298 void Init_zlib(void);
00299 
00300 /*--------- Exceptions --------*/
00301 
00302 static VALUE cZError, cStreamEnd, cNeedDict;
00303 static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
00304 
00305 static void
00306 raise_zlib_error(int err, const char *msg)
00307 {
00308     VALUE exc;
00309 
00310     if (!msg) {
00311         msg = zError(err);
00312     }
00313 
00314     switch(err) {
00315       case Z_STREAM_END:
00316         exc = rb_exc_new2(cStreamEnd, msg);
00317         break;
00318       case Z_NEED_DICT:
00319         exc = rb_exc_new2(cNeedDict, msg);
00320         break;
00321       case Z_STREAM_ERROR:
00322         exc = rb_exc_new2(cStreamError, msg);
00323         break;
00324       case Z_DATA_ERROR:
00325         exc = rb_exc_new2(cDataError, msg);
00326         break;
00327       case Z_BUF_ERROR:
00328         exc = rb_exc_new2(cBufError, msg);
00329         break;
00330       case Z_VERSION_ERROR:
00331         exc = rb_exc_new2(cVersionError, msg);
00332         break;
00333       case Z_MEM_ERROR:
00334         exc = rb_exc_new2(cMemError, msg);
00335         break;
00336       case Z_ERRNO:
00337         rb_sys_fail(msg);
00338         /* no return */
00339       default:
00340       {
00341           char buf[BUFSIZ];
00342           snprintf(buf, BUFSIZ, "unknown zlib error %d: %s", err, msg);
00343           exc = rb_exc_new2(cZError, buf);
00344       }
00345     }
00346 
00347     rb_exc_raise(exc);
00348 }
00349 
00350 
00351 /*--- Warning (in finalizer) ---*/
00352 
00353 static void
00354 finalizer_warn(const char *msg)
00355 {
00356     fprintf(stderr, "zlib(finalizer): %s\n", msg);
00357 }
00358 
00359 
00360 /*-------- module Zlib --------*/
00361 
00362 /*
00363  * Document-method: Zlib.zlib_version
00364  *
00365  * Returns the string which represents the version of zlib library.
00366  */
00367 static VALUE
00368 rb_zlib_version(VALUE klass)
00369 {
00370     VALUE str;
00371 
00372     str = rb_str_new2(zlibVersion());
00373     OBJ_TAINT(str);  /* for safe */
00374     return str;
00375 }
00376 
00377 #if SIZEOF_LONG > SIZEOF_INT
00378 static uLong
00379 checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
00380 {
00381     if (len > UINT_MAX) {
00382         do {
00383             sum = func(sum, ptr, UINT_MAX);
00384             ptr += UINT_MAX;
00385             len -= UINT_MAX;
00386         } while (len >= UINT_MAX);
00387     }
00388     if (len > 0) sum = func(sum, ptr, (uInt)len);
00389     return sum;
00390 }
00391 #else
00392 #define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
00393 #endif
00394 
00395 static VALUE
00396 do_checksum(argc, argv, func)
00397     int argc;
00398     VALUE *argv;
00399     uLong (*func)(uLong, const Bytef*, uInt);
00400 {
00401     VALUE str, vsum;
00402     unsigned long sum;
00403 
00404     rb_scan_args(argc, argv, "02", &str, &vsum);
00405 
00406     if (!NIL_P(vsum)) {
00407         sum = NUM2ULONG(vsum);
00408     }
00409     else if (NIL_P(str)) {
00410         sum = 0;
00411     }
00412     else {
00413         sum = func(0, Z_NULL, 0);
00414     }
00415 
00416     if (NIL_P(str)) {
00417         sum = func(sum, Z_NULL, 0);
00418     }
00419     else {
00420         StringValue(str);
00421         sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
00422     }
00423     return rb_uint2inum(sum);
00424 }
00425 
00426 /*
00427  * Document-method: Zlib.adler32
00428  *
00429  * call-seq: Zlib.adler32(string, adler)
00430  *
00431  * Calculates Adler-32 checksum for +string+, and returns updated value of
00432  * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
00433  * +adler+ is omitted, it assumes that the initial value is given to +adler+.
00434  *
00435  * FIXME: expression.
00436  */
00437 static VALUE
00438 rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
00439 {
00440     return do_checksum(argc, argv, adler32);
00441 }
00442 
00443 #ifdef HAVE_ADLER32_COMBINE
00444 /*
00445  * Document-method: Zlib.adler32_combine
00446  *
00447  * call-seq: Zlib.adler32_combine(adler1, adler2, len2)
00448  *
00449  * Combine two Adler-32 check values in to one.  +alder1+ is the first Adler-32
00450  * value, +adler2+ is the second Adler-32 value.  +len2+ is the length of the
00451  * string used to generate +adler2+.
00452  *
00453  */
00454 static VALUE
00455 rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
00456 {
00457   return ULONG2NUM(
00458         adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
00459 }
00460 #else
00461 #define rb_zlib_adler32_combine rb_f_notimplement
00462 #endif
00463 
00464 /*
00465  * Document-method: Zlib.crc32
00466  *
00467  * call-seq: Zlib.crc32(string, adler)
00468  *
00469  * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
00470  * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
00471  * assumes that the initial value is given to +crc+.
00472  *
00473  * FIXME: expression.
00474  */
00475 static VALUE
00476 rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
00477 {
00478     return do_checksum(argc, argv, crc32);
00479 }
00480 
00481 #ifdef HAVE_CRC32_COMBINE
00482 /*
00483  * Document-method: Zlib.crc32_combine
00484  *
00485  * call-seq: Zlib.crc32_combine(crc1, crc2, len2)
00486  *
00487  * Combine two CRC-32 check values in to one.  +crc1+ is the first CRC-32
00488  * value, +crc2+ is the second CRC-32 value.  +len2+ is the length of the
00489  * string used to generate +crc2+.
00490  *
00491  */
00492 static VALUE
00493 rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
00494 {
00495   return ULONG2NUM(
00496         crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
00497 }
00498 #else
00499 #define rb_zlib_crc32_combine rb_f_notimplement
00500 #endif
00501 
00502 /*
00503  * Document-method: Zlib.crc_table
00504  *
00505  * Returns the table for calculating CRC checksum as an array.
00506  */
00507 static VALUE
00508 rb_zlib_crc_table(VALUE obj)
00509 {
00510 #if !defined(HAVE_TYPE_Z_CRC_T)
00511     /* z_crc_t is defined since zlib-1.2.7. */
00512     typedef unsigned long z_crc_t;
00513 #endif
00514     const z_crc_t *crctbl;
00515     VALUE dst;
00516     int i;
00517 
00518     crctbl = get_crc_table();
00519     dst = rb_ary_new2(256);
00520 
00521     for (i = 0; i < 256; i++) {
00522         rb_ary_push(dst, rb_uint2inum(crctbl[i]));
00523     }
00524     return dst;
00525 }
00526 
00527 
00528 
00529 /*-------- zstream - internal APIs --------*/
00530 
00531 struct zstream {
00532     unsigned long flags;
00533     VALUE buf;
00534     long buf_filled;
00535     VALUE input;
00536     z_stream stream;
00537     const struct zstream_funcs {
00538         int (*reset)(z_streamp);
00539         int (*end)(z_streamp);
00540         int (*run)(z_streamp, int);
00541     } *func;
00542 };
00543 
00544 #define ZSTREAM_FLAG_READY      0x1
00545 #define ZSTREAM_FLAG_IN_STREAM  0x2
00546 #define ZSTREAM_FLAG_FINISHED   0x4
00547 #define ZSTREAM_FLAG_CLOSING    0x8
00548 #define ZSTREAM_FLAG_GZFILE     0x10 /* disallows yield from expand_buffer for
00549                                         gzip*/
00550 #define ZSTREAM_FLAG_UNUSED     0x20
00551 
00552 #define ZSTREAM_READY(z)       ((z)->flags |= ZSTREAM_FLAG_READY)
00553 #define ZSTREAM_IS_READY(z)    ((z)->flags & ZSTREAM_FLAG_READY)
00554 #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
00555 #define ZSTREAM_IS_CLOSING(z)  ((z)->flags & ZSTREAM_FLAG_CLOSING)
00556 #define ZSTREAM_IS_GZFILE(z)   ((z)->flags & ZSTREAM_FLAG_GZFILE)
00557 
00558 #define ZSTREAM_EXPAND_BUFFER_OK          0
00559 
00560 /* I think that more better value should be found,
00561    but I gave up finding it. B) */
00562 #define ZSTREAM_INITIAL_BUFSIZE       1024
00563 /* Allow a quick return when the thread is interrupted */
00564 #define ZSTREAM_AVAIL_OUT_STEP_MAX   16384
00565 #define ZSTREAM_AVAIL_OUT_STEP_MIN    2048
00566 
00567 static const struct zstream_funcs deflate_funcs = {
00568     deflateReset, deflateEnd, deflate,
00569 };
00570 
00571 static const struct zstream_funcs inflate_funcs = {
00572     inflateReset, inflateEnd, inflate,
00573 };
00574 
00575 struct zstream_run_args {
00576     struct zstream * z;
00577     int flush;         /* stream flush value for inflate() or deflate() */
00578     int interrupt;     /* stop processing the stream and return to ruby */
00579     int jump_state;    /* for buffer expansion block break or exception */
00580     int stream_output; /* for streaming zlib processing */
00581 };
00582 
00583 static voidpf
00584 zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
00585 {
00586     voidpf p = xmalloc(items * size);
00587     /* zlib FAQ: Valgrind (or some similar memory access checker) says that
00588        deflate is performing a conditional jump that depends on an
00589        uninitialized value.  Isn't that a bug?
00590        http://www.zlib.net/zlib_faq.html#faq36 */
00591     (void)VALGRIND_MAKE_MEM_DEFINED(p, items * size);
00592     return p;
00593 }
00594 
00595 static void
00596 zlib_mem_free(voidpf opaque, voidpf address)
00597 {
00598     xfree(address);
00599 }
00600 
00601 static void
00602 zstream_init(struct zstream *z, const struct zstream_funcs *func)
00603 {
00604     z->flags = 0;
00605     z->buf = Qnil;
00606     z->buf_filled = 0;
00607     z->input = Qnil;
00608     z->stream.zalloc = zlib_mem_alloc;
00609     z->stream.zfree = zlib_mem_free;
00610     z->stream.opaque = Z_NULL;
00611     z->stream.msg = Z_NULL;
00612     z->stream.next_in = Z_NULL;
00613     z->stream.avail_in = 0;
00614     z->stream.next_out = Z_NULL;
00615     z->stream.avail_out = 0;
00616     z->func = func;
00617 }
00618 
00619 #define zstream_init_deflate(z)   zstream_init((z), &deflate_funcs)
00620 #define zstream_init_inflate(z)   zstream_init((z), &inflate_funcs)
00621 
00622 static void
00623 zstream_expand_buffer(struct zstream *z)
00624 {
00625     if (NIL_P(z->buf)) {
00626         zstream_expand_buffer_into(z, ZSTREAM_INITIAL_BUFSIZE);
00627         return;
00628     }
00629 
00630     if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
00631         if (z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
00632             int state = 0;
00633             VALUE self = (VALUE)z->stream.opaque;
00634 
00635             rb_str_resize(z->buf, z->buf_filled);
00636             RBASIC(z->buf)->klass = rb_cString;
00637             OBJ_INFECT(z->buf, self);
00638 
00639             rb_protect(rb_yield, z->buf, &state);
00640 
00641             z->buf = Qnil;
00642             zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
00643 
00644             if (state)
00645                 rb_jump_tag(state);
00646 
00647             return;
00648         }
00649         else {
00650             zstream_expand_buffer_into(z,
00651                     ZSTREAM_AVAIL_OUT_STEP_MAX - z->buf_filled);
00652         }
00653     }
00654     else {
00655         if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
00656             z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
00657         }
00658         else {
00659             long inc = z->buf_filled / 2;
00660             if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
00661                 inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
00662             }
00663             rb_str_resize(z->buf, z->buf_filled + inc);
00664             z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
00665                 (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
00666         }
00667         z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00668     }
00669 }
00670 
00671 static void
00672 zstream_expand_buffer_into(struct zstream *z, unsigned long size)
00673 {
00674     if (NIL_P(z->buf)) {
00675         /* I uses rb_str_new here not rb_str_buf_new because
00676            rb_str_buf_new makes a zero-length string. */
00677         z->buf = rb_str_new(0, size);
00678         z->buf_filled = 0;
00679         z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
00680         z->stream.avail_out = MAX_UINT(size);
00681         RBASIC(z->buf)->klass = 0;
00682     }
00683     else if (z->stream.avail_out != size) {
00684         rb_str_resize(z->buf, z->buf_filled + size);
00685         z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00686         z->stream.avail_out = MAX_UINT(size);
00687     }
00688 }
00689 
00690 static void *
00691 zstream_expand_buffer_protect(void *ptr)
00692 {
00693     struct zstream *z = (struct zstream *)ptr;
00694     int state = 0;
00695 
00696     rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
00697 
00698     return (void *)(VALUE)state;
00699 }
00700 
00701 static int
00702 zstream_expand_buffer_without_gvl(struct zstream *z)
00703 {
00704     char * new_str;
00705     long inc, len;
00706 
00707     if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
00708         z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
00709     }
00710     else {
00711         inc = z->buf_filled / 2;
00712         if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
00713             inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
00714         }
00715 
00716         len = z->buf_filled + inc;
00717 
00718         new_str = ruby_xrealloc(RSTRING(z->buf)->as.heap.ptr, len + 1);
00719 
00720         /* from rb_str_resize */
00721         RSTRING(z->buf)->as.heap.ptr = new_str;
00722         RSTRING(z->buf)->as.heap.ptr[len] = '\0'; /* sentinel */
00723         RSTRING(z->buf)->as.heap.len =
00724             RSTRING(z->buf)->as.heap.aux.capa = len;
00725 
00726         z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
00727             (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
00728     }
00729     z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00730 
00731     return ZSTREAM_EXPAND_BUFFER_OK;
00732 }
00733 
00734 static void
00735 zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
00736 {
00737     if (NIL_P(z->buf)) {
00738         z->buf = rb_str_buf_new(len);
00739         rb_str_buf_cat(z->buf, (const char*)src, len);
00740         z->buf_filled = len;
00741         z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
00742         z->stream.avail_out = 0;
00743         RBASIC(z->buf)->klass = 0;
00744         return;
00745     }
00746 
00747     if (RSTRING_LEN(z->buf) < z->buf_filled + len) {
00748         rb_str_resize(z->buf, z->buf_filled + len);
00749         z->stream.avail_out = 0;
00750     }
00751     else {
00752         if (z->stream.avail_out >= (uInt)len) {
00753             z->stream.avail_out -= (uInt)len;
00754         }
00755         else {
00756             z->stream.avail_out = 0;
00757         }
00758     }
00759     memcpy(RSTRING_PTR(z->buf) + z->buf_filled, src, len);
00760     z->buf_filled += len;
00761     z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00762 }
00763 
00764 #define zstream_append_buffer2(z,v) \
00765     zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v))
00766 
00767 static VALUE
00768 zstream_detach_buffer(struct zstream *z)
00769 {
00770     VALUE dst, self = (VALUE)z->stream.opaque;
00771 
00772     if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
00773             rb_block_given_p()) {
00774         /* prevent tiny yields mid-stream, save for next
00775          * zstream_expand_buffer() or stream end */
00776         return Qnil;
00777     }
00778 
00779     if (NIL_P(z->buf)) {
00780         dst = rb_str_new(0, 0);
00781     }
00782     else {
00783         dst = z->buf;
00784         rb_str_resize(dst, z->buf_filled);
00785         RBASIC(dst)->klass = rb_cString;
00786     }
00787 
00788     OBJ_INFECT(dst, self);
00789 
00790     z->buf = Qnil;
00791     z->buf_filled = 0;
00792     z->stream.next_out = 0;
00793     z->stream.avail_out = 0;
00794 
00795     if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
00796         rb_yield(dst);
00797         dst = Qnil;
00798     }
00799 
00800     return dst;
00801 }
00802 
00803 static VALUE
00804 zstream_shift_buffer(struct zstream *z, long len)
00805 {
00806     VALUE dst;
00807     long buflen;
00808 
00809     if (z->buf_filled <= len) {
00810         return zstream_detach_buffer(z);
00811     }
00812 
00813     dst = rb_str_subseq(z->buf, 0, len);
00814     RBASIC(dst)->klass = rb_cString;
00815     z->buf_filled -= len;
00816     memmove(RSTRING_PTR(z->buf), RSTRING_PTR(z->buf) + len,
00817             z->buf_filled);
00818     z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00819     buflen = RSTRING_LEN(z->buf) - z->buf_filled;
00820     if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
00821         buflen = ZSTREAM_AVAIL_OUT_STEP_MAX;
00822     }
00823     z->stream.avail_out = (uInt)buflen;
00824 
00825     return dst;
00826 }
00827 
00828 static void
00829 zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
00830 {
00831     if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
00832         zstream_expand_buffer_into(z, len);
00833     }
00834 
00835     memmove(RSTRING_PTR(z->buf) + len, RSTRING_PTR(z->buf), z->buf_filled);
00836     memmove(RSTRING_PTR(z->buf), b, len);
00837     z->buf_filled+=len;
00838     if (z->stream.avail_out > 0) {
00839         if (len > z->stream.avail_out) len = z->stream.avail_out;
00840         z->stream.next_out+=len;
00841         z->stream.avail_out-=(uInt)len;
00842     }
00843 }
00844 
00845 static void
00846 zstream_buffer_ungetbyte(struct zstream *z, int c)
00847 {
00848     if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
00849         zstream_expand_buffer(z);
00850     }
00851 
00852     memmove(RSTRING_PTR(z->buf) + 1, RSTRING_PTR(z->buf), z->buf_filled);
00853     RSTRING_PTR(z->buf)[0] = (char)c;
00854     z->buf_filled++;
00855     if (z->stream.avail_out > 0) {
00856         z->stream.next_out++;
00857         z->stream.avail_out--;
00858     }
00859 }
00860 
00861 static void
00862 zstream_append_input(struct zstream *z, const Bytef *src, long len)
00863 {
00864     if (len <= 0) return;
00865 
00866     if (NIL_P(z->input)) {
00867         z->input = rb_str_buf_new(len);
00868         rb_str_buf_cat(z->input, (const char*)src, len);
00869         RBASIC(z->input)->klass = 0;
00870     }
00871     else {
00872         rb_str_buf_cat(z->input, (const char*)src, len);
00873     }
00874 }
00875 
00876 #define zstream_append_input2(z,v)\
00877     RB_GC_GUARD(v),\
00878     zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
00879 
00880 static void
00881 zstream_discard_input(struct zstream *z, long len)
00882 {
00883     if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) {
00884         z->input = Qnil;
00885     }
00886     else {
00887         memmove(RSTRING_PTR(z->input), RSTRING_PTR(z->input) + len,
00888                 RSTRING_LEN(z->input) - len);
00889         rb_str_resize(z->input, RSTRING_LEN(z->input) - len);
00890     }
00891 }
00892 
00893 static void
00894 zstream_reset_input(struct zstream *z)
00895 {
00896     z->input = Qnil;
00897 }
00898 
00899 static void
00900 zstream_passthrough_input(struct zstream *z)
00901 {
00902     if (!NIL_P(z->input)) {
00903         zstream_append_buffer2(z, z->input);
00904         z->input = Qnil;
00905     }
00906 }
00907 
00908 static VALUE
00909 zstream_detach_input(struct zstream *z)
00910 {
00911     VALUE dst;
00912 
00913     if (NIL_P(z->input)) {
00914         dst = rb_str_new(0, 0);
00915     }
00916     else {
00917         dst = z->input;
00918         RBASIC(dst)->klass = rb_cString;
00919     }
00920     z->input = Qnil;
00921     RBASIC(dst)->klass = rb_cString;
00922     return dst;
00923 }
00924 
00925 static void
00926 zstream_reset(struct zstream *z)
00927 {
00928     int err;
00929 
00930     err = z->func->reset(&z->stream);
00931     if (err != Z_OK) {
00932         raise_zlib_error(err, z->stream.msg);
00933     }
00934     z->flags = ZSTREAM_FLAG_READY;
00935     z->buf = Qnil;
00936     z->buf_filled = 0;
00937     z->stream.next_out = 0;
00938     z->stream.avail_out = 0;
00939     zstream_reset_input(z);
00940 }
00941 
00942 static VALUE
00943 zstream_end(struct zstream *z)
00944 {
00945     int err;
00946 
00947     if (!ZSTREAM_IS_READY(z)) {
00948         rb_warning("attempt to close uninitialized zstream; ignored.");
00949         return Qnil;
00950     }
00951     if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
00952         rb_warning("attempt to close unfinished zstream; reset forced.");
00953         zstream_reset(z);
00954     }
00955 
00956     zstream_reset_input(z);
00957     err = z->func->end(&z->stream);
00958     if (err != Z_OK) {
00959         raise_zlib_error(err, z->stream.msg);
00960     }
00961     z->flags = 0;
00962     return Qnil;
00963 }
00964 
00965 static void *
00966 zstream_run_func(void *ptr)
00967 {
00968     struct zstream_run_args *args = (struct zstream_run_args *)ptr;
00969     int err, state, flush = args->flush;
00970     struct zstream *z = args->z;
00971     uInt n;
00972 
00973     err = Z_OK;
00974     while (!args->interrupt) {
00975         n = z->stream.avail_out;
00976         err = z->func->run(&z->stream, flush);
00977         z->buf_filled += n - z->stream.avail_out;
00978 
00979         if (err == Z_STREAM_END) {
00980             z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
00981             z->flags |= ZSTREAM_FLAG_FINISHED;
00982             break;
00983         }
00984 
00985         if (err != Z_OK && err != Z_BUF_ERROR)
00986             break;
00987 
00988         if (z->stream.avail_out > 0) {
00989             z->flags |= ZSTREAM_FLAG_IN_STREAM;
00990             break;
00991         }
00992 
00993         if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
00994             /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
00995             /* but deflate() could be called with avail_in == 0 (there's hidden buffer
00996                in zstream->state) */
00997             z->flags |= ZSTREAM_FLAG_IN_STREAM;
00998             break;
00999         }
01000 
01001         if (args->stream_output) {
01002             state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
01003                                                         (void *)z);
01004         } else {
01005             state = zstream_expand_buffer_without_gvl(z);
01006         }
01007 
01008         if (state) {
01009             err = Z_OK; /* buffer expanded but stream processing was stopped */
01010             args->jump_state = state;
01011             break;
01012         }
01013     }
01014 
01015     return (void *)(VALUE)err;
01016 }
01017 
01018 /*
01019  * There is no safe way to interrupt z->run->func().
01020  */
01021 static void
01022 zstream_unblock_func(void *ptr)
01023 {
01024     struct zstream_run_args *args = (struct zstream_run_args *)ptr;
01025 
01026     args->interrupt = 1;
01027 }
01028 
01029 static void
01030 zstream_run(struct zstream *z, Bytef *src, long len, int flush)
01031 {
01032     struct zstream_run_args args;
01033     int err;
01034     volatile VALUE guard = Qnil;
01035 
01036     args.z = z;
01037     args.flush = flush;
01038     args.interrupt = 0;
01039     args.jump_state = 0;
01040     args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
01041 
01042     if (NIL_P(z->input) && len == 0) {
01043         z->stream.next_in = (Bytef*)"";
01044         z->stream.avail_in = 0;
01045     }
01046     else {
01047         zstream_append_input(z, src, len);
01048         z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
01049         z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
01050         /* keep reference to `z->input' so as not to be garbage collected
01051            after zstream_reset_input() and prevent `z->stream.next_in'
01052            from dangling. */
01053         guard = z->input;
01054     }
01055 
01056     if (z->stream.avail_out == 0) {
01057         zstream_expand_buffer(z);
01058     }
01059 
01060 loop:
01061     err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
01062                                                  zstream_unblock_func, (void *)&args);
01063 
01064     if (flush != Z_FINISH && err == Z_BUF_ERROR
01065             && z->stream.avail_out > 0) {
01066         z->flags |= ZSTREAM_FLAG_IN_STREAM;
01067     }
01068 
01069     zstream_reset_input(z);
01070 
01071     if (err != Z_OK && err != Z_STREAM_END) {
01072         if (z->stream.avail_in > 0) {
01073             zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
01074         }
01075         if (err == Z_NEED_DICT) {
01076             VALUE self = (VALUE)z->stream.opaque;
01077             if (self) {
01078                 VALUE dicts = rb_ivar_get(self, id_dictionaries);
01079                 VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
01080                 if (!NIL_P(dict)) {
01081                     rb_inflate_set_dictionary(self, dict);
01082                     goto loop;
01083                 }
01084             }
01085         }
01086         raise_zlib_error(err, z->stream.msg);
01087     }
01088 
01089     if (z->stream.avail_in > 0) {
01090         zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
01091         RB_GC_GUARD(guard) = Qnil; /* prevent tail call to make guard effective */
01092     }
01093 
01094     if (args.jump_state)
01095         rb_jump_tag(args.jump_state);
01096 }
01097 
01098 static VALUE
01099 zstream_sync(struct zstream *z, Bytef *src, long len)
01100 {
01101     /* VALUE rest; */
01102     int err;
01103 
01104     if (!NIL_P(z->input)) {
01105         z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
01106         z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
01107         err = inflateSync(&z->stream);
01108         if (err == Z_OK) {
01109             zstream_discard_input(z,
01110                                   RSTRING_LEN(z->input) - z->stream.avail_in);
01111             zstream_append_input(z, src, len);
01112             return Qtrue;
01113         }
01114         zstream_reset_input(z);
01115         if (err != Z_DATA_ERROR) {
01116             /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
01117             raise_zlib_error(err, z->stream.msg);
01118         }
01119     }
01120 
01121     if (len <= 0) return Qfalse;
01122 
01123     z->stream.next_in = src;
01124     z->stream.avail_in = MAX_UINT(len);
01125     err = inflateSync(&z->stream);
01126     if (err == Z_OK) {
01127         zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
01128         return Qtrue;
01129     }
01130     if (err != Z_DATA_ERROR) {
01131         /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
01132         raise_zlib_error(err, z->stream.msg);
01133     }
01134     return Qfalse;
01135 }
01136 
01137 static void
01138 zstream_mark(struct zstream *z)
01139 {
01140     rb_gc_mark(z->buf);
01141     rb_gc_mark(z->input);
01142 }
01143 
01144 static void
01145 zstream_finalize(struct zstream *z)
01146 {
01147     int err = z->func->end(&z->stream);
01148     if (err == Z_STREAM_ERROR)
01149         finalizer_warn("the stream state was inconsistent.");
01150     if (err == Z_DATA_ERROR)
01151         finalizer_warn("the stream was freed prematurely.");
01152 }
01153 
01154 static void
01155 zstream_free(struct zstream *z)
01156 {
01157     if (ZSTREAM_IS_READY(z)) {
01158         zstream_finalize(z);
01159     }
01160     xfree(z);
01161 }
01162 
01163 static VALUE
01164 zstream_new(VALUE klass, const struct zstream_funcs *funcs)
01165 {
01166     VALUE obj;
01167     struct zstream *z;
01168 
01169     obj = Data_Make_Struct(klass, struct zstream,
01170                            zstream_mark, zstream_free, z);
01171     zstream_init(z, funcs);
01172     z->stream.opaque = (voidpf)obj;
01173     return obj;
01174 }
01175 
01176 #define zstream_deflate_new(klass)  zstream_new((klass), &deflate_funcs)
01177 #define zstream_inflate_new(klass)  zstream_new((klass), &inflate_funcs)
01178 
01179 static struct zstream *
01180 get_zstream(VALUE obj)
01181 {
01182     struct zstream *z;
01183 
01184     Data_Get_Struct(obj, struct zstream, z);
01185     if (!ZSTREAM_IS_READY(z)) {
01186         rb_raise(cZError, "stream is not ready");
01187     }
01188     return z;
01189 }
01190 
01191 
01192 /* ------------------------------------------------------------------------- */
01193 
01194 /*
01195  * Document-class: Zlib::ZStream
01196  *
01197  * Zlib::ZStream is the abstract class for the stream which handles the
01198  * compressed data. The operations are defined in the subclasses:
01199  * Zlib::Deflate for compression, and Zlib::Inflate for decompression.
01200  *
01201  * An instance of Zlib::ZStream has one stream (struct zstream in the source)
01202  * and two variable-length buffers which associated to the input (next_in) of
01203  * the stream and the output (next_out) of the stream. In this document,
01204  * "input buffer" means the buffer for input, and "output buffer" means the
01205  * buffer for output.
01206  *
01207  * Data input into an instance of Zlib::ZStream are temporally stored into
01208  * the end of input buffer, and then data in input buffer are processed from
01209  * the beginning of the buffer until no more output from the stream is
01210  * produced (i.e. until avail_out > 0 after processing).  During processing,
01211  * output buffer is allocated and expanded automatically to hold all output
01212  * data.
01213  *
01214  * Some particular instance methods consume the data in output buffer and
01215  * return them as a String.
01216  *
01217  * Here is an ascii art for describing above:
01218  *
01219  *    +================ an instance of Zlib::ZStream ================+
01220  *    ||                                                            ||
01221  *    ||     +--------+          +-------+          +--------+      ||
01222  *    ||  +--| output |<---------|zstream|<---------| input  |<--+  ||
01223  *    ||  |  | buffer |  next_out+-------+next_in   | buffer |   |  ||
01224  *    ||  |  +--------+                             +--------+   |  ||
01225  *    ||  |                                                      |  ||
01226  *    +===|======================================================|===+
01227  *        |                                                      |
01228  *        v                                                      |
01229  *    "output data"                                         "input data"
01230  *
01231  * If an error occurs during processing input buffer, an exception which is a
01232  * subclass of Zlib::Error is raised.  At that time, both input and output
01233  * buffer keep their conditions at the time when the error occurs.
01234  *
01235  * == Method Catalogue
01236  *
01237  * Many of the methods in this class are fairly low-level and unlikely to be
01238  * of interest to users.  In fact, users are unlikely to use this class
01239  * directly; rather they will be interested in Zlib::Inflate and
01240  * Zlib::Deflate.
01241  *
01242  * The higher level methods are listed below.
01243  *
01244  * - #total_in
01245  * - #total_out
01246  * - #data_type
01247  * - #adler
01248  * - #reset
01249  * - #finish
01250  * - #finished?
01251  * - #close
01252  * - #closed?
01253  */
01254 
01255 /*
01256  * Closes the stream. All operations on the closed stream will raise an
01257  * exception.
01258  */
01259 static VALUE
01260 rb_zstream_end(VALUE obj)
01261 {
01262     zstream_end(get_zstream(obj));
01263     return Qnil;
01264 }
01265 
01266 /*
01267  * Resets and initializes the stream. All data in both input and output buffer
01268  * are discarded.
01269  */
01270 static VALUE
01271 rb_zstream_reset(VALUE obj)
01272 {
01273     zstream_reset(get_zstream(obj));
01274     return Qnil;
01275 }
01276 
01277 /*
01278  * call-seq:
01279  *   finish                 -> String
01280  *   finish { |chunk| ... } -> nil
01281  *
01282  * Finishes the stream and flushes output buffer.  If a block is given each
01283  * chunk is yielded to the block until the input buffer has been flushed to
01284  * the output buffer.
01285  */
01286 static VALUE
01287 rb_zstream_finish(VALUE obj)
01288 {
01289     struct zstream *z = get_zstream(obj);
01290 
01291     zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01292 
01293     return zstream_detach_buffer(z);
01294 }
01295 
01296 /*
01297  * call-seq:
01298  *   flush_next_out                 -> String
01299  *   flush_next_out { |chunk| ... } -> nil
01300  *
01301  * Flushes output buffer and returns all data in that buffer.  If a block is
01302  * given each chunk is yielded to the block until the current output buffer
01303  * has been flushed.
01304  */
01305 static VALUE
01306 rb_zstream_flush_next_in(VALUE obj)
01307 {
01308     struct zstream *z;
01309     VALUE dst;
01310 
01311     Data_Get_Struct(obj, struct zstream, z);
01312     dst = zstream_detach_input(z);
01313     OBJ_INFECT(dst, obj);
01314     return dst;
01315 }
01316 
01317 /*
01318  * Flushes output buffer and returns all data in that buffer.
01319  */
01320 static VALUE
01321 rb_zstream_flush_next_out(VALUE obj)
01322 {
01323     struct zstream *z;
01324 
01325     Data_Get_Struct(obj, struct zstream, z);
01326 
01327     return zstream_detach_buffer(z);
01328 }
01329 
01330 /*
01331  * Returns number of bytes of free spaces in output buffer.  Because the free
01332  * space is allocated automatically, this method returns 0 normally.
01333  */
01334 static VALUE
01335 rb_zstream_avail_out(VALUE obj)
01336 {
01337     struct zstream *z;
01338     Data_Get_Struct(obj, struct zstream, z);
01339     return rb_uint2inum(z->stream.avail_out);
01340 }
01341 
01342 /*
01343  * Allocates +size+ bytes of free space in the output buffer. If there are more
01344  * than +size+ bytes already in the buffer, the buffer is truncated. Because
01345  * free space is allocated automatically, you usually don't need to use this
01346  * method.
01347  */
01348 static VALUE
01349 rb_zstream_set_avail_out(VALUE obj, VALUE size)
01350 {
01351     struct zstream *z = get_zstream(obj);
01352 
01353     Check_Type(size, T_FIXNUM);
01354     zstream_expand_buffer_into(z, FIX2INT(size));
01355     return size;
01356 }
01357 
01358 /*
01359  * Returns bytes of data in the input buffer. Normally, returns 0.
01360  */
01361 static VALUE
01362 rb_zstream_avail_in(VALUE obj)
01363 {
01364     struct zstream *z;
01365     Data_Get_Struct(obj, struct zstream, z);
01366     return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING_LEN(z->input)));
01367 }
01368 
01369 /*
01370  * Returns the total bytes of the input data to the stream.  FIXME
01371  */
01372 static VALUE
01373 rb_zstream_total_in(VALUE obj)
01374 {
01375     return rb_uint2inum(get_zstream(obj)->stream.total_in);
01376 }
01377 
01378 /*
01379  * Returns the total bytes of the output data from the stream.  FIXME
01380  */
01381 static VALUE
01382 rb_zstream_total_out(VALUE obj)
01383 {
01384     return rb_uint2inum(get_zstream(obj)->stream.total_out);
01385 }
01386 
01387 /*
01388  * Guesses the type of the data which have been inputed into the stream. The
01389  * returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
01390  * <tt>UNKNOWN</tt>.
01391  */
01392 static VALUE
01393 rb_zstream_data_type(VALUE obj)
01394 {
01395     return INT2FIX(get_zstream(obj)->stream.data_type);
01396 }
01397 
01398 /*
01399  * Returns the adler-32 checksum.
01400  */
01401 static VALUE
01402 rb_zstream_adler(VALUE obj)
01403 {
01404         return rb_uint2inum(get_zstream(obj)->stream.adler);
01405 }
01406 
01407 /*
01408  * Returns true if the stream is finished.
01409  */
01410 static VALUE
01411 rb_zstream_finished_p(VALUE obj)
01412 {
01413     return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
01414 }
01415 
01416 /*
01417  * Returns true if the stream is closed.
01418  */
01419 static VALUE
01420 rb_zstream_closed_p(VALUE obj)
01421 {
01422     struct zstream *z;
01423     Data_Get_Struct(obj, struct zstream, z);
01424     return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
01425 }
01426 
01427 
01428 /* ------------------------------------------------------------------------- */
01429 
01430 /*
01431  * Document-class: Zlib::Deflate
01432  *
01433  * Zlib::Deflate is the class for compressing data.  See Zlib::ZStream for more
01434  * information.
01435  */
01436 
01437 #define FIXNUMARG(val, ifnil) \
01438     (NIL_P((val)) ? (ifnil) \
01439     : ((void)Check_Type((val), T_FIXNUM), FIX2INT((val))))
01440 
01441 #define ARG_LEVEL(val)     FIXNUMARG((val), Z_DEFAULT_COMPRESSION)
01442 #define ARG_WBITS(val)     FIXNUMARG((val), MAX_WBITS)
01443 #define ARG_MEMLEVEL(val)  FIXNUMARG((val), DEF_MEM_LEVEL)
01444 #define ARG_STRATEGY(val)  FIXNUMARG((val), Z_DEFAULT_STRATEGY)
01445 #define ARG_FLUSH(val)     FIXNUMARG((val), Z_NO_FLUSH)
01446 
01447 
01448 static VALUE
01449 rb_deflate_s_allocate(VALUE klass)
01450 {
01451     return zstream_deflate_new(klass);
01452 }
01453 
01454 /*
01455  * Document-method: Zlib::Deflate.new
01456  *
01457  * call-seq:
01458  *   Zlib::Deflate.new(level=DEFAULT_COMPRESSION, window_bits=MAX_WBITS, mem_level=DEF_MEM_LEVEL, strategy=DEFAULT_STRATEGY)
01459  *
01460  * Creates a new deflate stream for compression. If a given argument is nil,
01461  * the default value of that argument is used.
01462  *
01463  * The +level+ sets the compression level for the deflate stream between 0 (no
01464  * compression) and 9 (best compression. The following constants have been
01465  * defined to make code more readable:
01466  *
01467  * * Zlib::NO_COMPRESSION = 0
01468  * * Zlib::BEST_SPEED = 1
01469  * * Zlib::DEFAULT_COMPRESSION = 6
01470  * * Zlib::BEST_COMPRESSION = 9
01471  *
01472  * The +window_bits+ sets the size of the history buffer and should be between
01473  * 8 and 15.  Larger values of this parameter result in better compression at
01474  * the expense of memory usage.
01475  *
01476  * The +mem_level+ specifies how much memory should be allocated for the
01477  * internal compression state.  1 uses minimum memory but is slow and reduces
01478  * compression ratio while 9 uses maximum memory for optimal speed.  The
01479  * default value is 8. Two constants are defined:
01480  *
01481  * * Zlib::DEF_MEM_LEVEL
01482  * * Zlib::MAX_MEM_LEVEL
01483  *
01484  * The +strategy+ sets the deflate compression strategy.  The following
01485  * strategies are available:
01486  *
01487  * Zlib::DEFAULT_STRATEGY:: For normal data
01488  * Zlib::FILTERED:: For data produced by a filter or predictor
01489  * Zlib::FIXED:: Prevents dynamic Huffman codes
01490  * Zlib::HUFFMAN_ONLY:: Prevents string matching
01491  * Zlib::RLE:: Designed for better compression of PNG image data
01492  *
01493  * See the constants for further description.
01494  *
01495  * == Examples
01496  *
01497  * === Basic
01498  *
01499  *   open "compressed.file", "w+" do |io|
01500  *     io << Zlib::Deflate.new.deflate(File.read("big.file"))
01501  *   end
01502  *
01503  * === Custom compression
01504  *
01505  *   open "compressed.file", "w+" do |compressed_io|
01506  *     deflate = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
01507  *                                 Zlib::MAX_WBITS,
01508  *                                 Zlib::MAX_MEM_LEVEL,
01509  *                                 Zlib::HUFFMAN_ONLY)
01510  *
01511  *     begin
01512  *       open "big.file" do |big_io|
01513  *         until big_io.eof? do
01514  *           compressed_io << zd.deflate(big_io.read(16384))
01515  *         end
01516  *       end
01517  *     ensure
01518  *       deflate.close
01519  *     end
01520  *   end
01521  *
01522  * While this example will work, for best optimization review the flags for
01523  * your specific time, memory usage and output space requirements.
01524  */
01525 static VALUE
01526 rb_deflate_initialize(int argc, VALUE *argv, VALUE obj)
01527 {
01528     struct zstream *z;
01529     VALUE level, wbits, memlevel, strategy;
01530     int err;
01531 
01532     rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
01533     Data_Get_Struct(obj, struct zstream, z);
01534 
01535     err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
01536                        ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
01537                        ARG_STRATEGY(strategy));
01538     if (err != Z_OK) {
01539         raise_zlib_error(err, z->stream.msg);
01540     }
01541     ZSTREAM_READY(z);
01542 
01543     return obj;
01544 }
01545 
01546 /*
01547  * Document-method: Zlib::Deflate#initialize_copy
01548  *
01549  * Duplicates the deflate stream.
01550  */
01551 static VALUE
01552 rb_deflate_init_copy(VALUE self, VALUE orig)
01553 {
01554     struct zstream *z1, *z2;
01555     int err;
01556 
01557     Data_Get_Struct(self, struct zstream, z1);
01558     z2 = get_zstream(orig);
01559 
01560     err = deflateCopy(&z1->stream, &z2->stream);
01561     if (err != Z_OK) {
01562         raise_zlib_error(err, 0);
01563     }
01564     z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
01565     z1->buf   = NIL_P(z2->buf)   ? Qnil : rb_str_dup(z2->buf);
01566     z1->buf_filled = z2->buf_filled;
01567     z1->flags = z2->flags;
01568 
01569     return self;
01570 }
01571 
01572 static VALUE
01573 deflate_run(VALUE args)
01574 {
01575     struct zstream *z = (struct zstream*)((VALUE*)args)[0];
01576     VALUE src = ((VALUE*)args)[1];
01577 
01578     zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_FINISH);
01579     return zstream_detach_buffer(z);
01580 }
01581 
01582 /*
01583  * Document-method: Zlib::Deflate.deflate
01584  *
01585  * call-seq:
01586  *   Zlib.deflate(string[, level])
01587  *   Zlib::Deflate.deflate(string[, level])
01588  *
01589  * Compresses the given +string+. Valid values of level are
01590  * Zlib::NO_COMPRESSION, Zlib::BEST_SPEED, Zlib::BEST_COMPRESSION,
01591  * Zlib::DEFAULT_COMPRESSION, or an integer from 0 to 9 (the default is 6).
01592  *
01593  * This method is almost equivalent to the following code:
01594  *
01595  *   def deflate(string, level)
01596  *     z = Zlib::Deflate.new(level)
01597  *     dst = z.deflate(string, Zlib::FINISH)
01598  *     z.close
01599  *     dst
01600  *   end
01601  *
01602  * See also Zlib.inflate
01603  *
01604  */
01605 static VALUE
01606 rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass)
01607 {
01608     struct zstream z;
01609     VALUE src, level, dst, args[2];
01610     int err, lev;
01611 
01612     rb_scan_args(argc, argv, "11", &src, &level);
01613 
01614     lev = ARG_LEVEL(level);
01615     StringValue(src);
01616     zstream_init_deflate(&z);
01617     err = deflateInit(&z.stream, lev);
01618     if (err != Z_OK) {
01619         raise_zlib_error(err, z.stream.msg);
01620     }
01621     ZSTREAM_READY(&z);
01622 
01623     args[0] = (VALUE)&z;
01624     args[1] = src;
01625     dst = rb_ensure(deflate_run, (VALUE)args, zstream_end, (VALUE)&z);
01626 
01627     OBJ_INFECT(dst, src);
01628     return dst;
01629 }
01630 
01631 static void
01632 do_deflate(struct zstream *z, VALUE src, int flush)
01633 {
01634     if (NIL_P(src)) {
01635         zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01636         return;
01637     }
01638     StringValue(src);
01639     if (flush != Z_NO_FLUSH || RSTRING_LEN(src) > 0) { /* prevent BUF_ERROR */
01640         zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), flush);
01641     }
01642 }
01643 
01644 /*
01645  * Document-method: Zlib::Deflate#deflate
01646  *
01647  * call-seq:
01648  *   z.deflate(string, flush = Zlib::NO_FLUSH)                 -> String
01649  *   z.deflate(string, flush = Zlib::NO_FLUSH) { |chunk| ... } -> nil
01650  *
01651  * Inputs +string+ into the deflate stream and returns the output from the
01652  * stream.  On calling this method, both the input and the output buffers of
01653  * the stream are flushed.  If +string+ is nil, this method finishes the
01654  * stream, just like Zlib::ZStream#finish.
01655  *
01656  * If a block is given consecutive deflated chunks from the +string+ are
01657  * yielded to the block and +nil+ is returned.
01658  *
01659  * The +flush+ parameter specifies the flush mode.  The following constants
01660  * may be used:
01661  *
01662  * Zlib::NO_FLUSH:: The default
01663  * Zlib::SYNC_FLUSH:: Flushes the output to a byte boundary
01664  * Zlib::FULL_FLUSH:: SYNC_FLUSH + resets the compression state
01665  * Zlib::FINISH:: Pending input is processed, pending output is flushed.
01666  *
01667  * See the constants for further description.
01668  *
01669  */
01670 static VALUE
01671 rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
01672 {
01673     struct zstream *z = get_zstream(obj);
01674     VALUE src, flush;
01675 
01676     rb_scan_args(argc, argv, "11", &src, &flush);
01677     OBJ_INFECT(obj, src);
01678     do_deflate(z, src, ARG_FLUSH(flush));
01679 
01680     return zstream_detach_buffer(z);
01681 }
01682 
01683 /*
01684  * Document-method: Zlib::Deflate#<<
01685  *
01686  * call-seq: << string
01687  *
01688  * Inputs +string+ into the deflate stream just like Zlib::Deflate#deflate, but
01689  * returns the Zlib::Deflate object itself.  The output from the stream is
01690  * preserved in output buffer.
01691  */
01692 static VALUE
01693 rb_deflate_addstr(VALUE obj, VALUE src)
01694 {
01695     OBJ_INFECT(obj, src);
01696     do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
01697     return obj;
01698 }
01699 
01700 /*
01701  * Document-method: Zlib::Deflate#flush
01702  *
01703  * call-seq:
01704  *   flush(flush = Zlib::SYNC_FLUSH)                 -> String
01705  *   flush(flush = Zlib::SYNC_FLUSH) { |chunk| ... } -> nil
01706  *
01707  * This method is equivalent to <tt>deflate('', flush)</tt>. This method is
01708  * just provided to improve the readability of your Ruby program.  If a block
01709  * is given chunks of deflate output are yielded to the block until the buffer
01710  * is flushed.
01711  *
01712  * See Zlib::Deflate#deflate for detail on the +flush+ constants NO_FLUSH,
01713  * SYNC_FLUSH, FULL_FLUSH and FINISH.
01714  */
01715 static VALUE
01716 rb_deflate_flush(int argc, VALUE *argv, VALUE obj)
01717 {
01718     struct zstream *z = get_zstream(obj);
01719     VALUE v_flush;
01720     int flush;
01721 
01722     rb_scan_args(argc, argv, "01", &v_flush);
01723     flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
01724     if (flush != Z_NO_FLUSH) {  /* prevent Z_BUF_ERROR */
01725         zstream_run(z, (Bytef*)"", 0, flush);
01726     }
01727 
01728     return zstream_detach_buffer(z);
01729 }
01730 
01731 /*
01732  * Document-method: Zlib::Deflate.params
01733  *
01734  * call-seq: params(level, strategy)
01735  *
01736  * Changes the parameters of the deflate stream to allow changes between
01737  * different types of data that require different types of compression.  Any
01738  * unprocessed data is flushed before changing the params.
01739  *
01740  * See Zlib::Deflate.new for a description of +level+ and +strategy+.
01741  *
01742  */
01743 static VALUE
01744 rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy)
01745 {
01746     struct zstream *z = get_zstream(obj);
01747     int level, strategy;
01748     int err;
01749     uInt n;
01750 
01751     level = ARG_LEVEL(v_level);
01752     strategy = ARG_STRATEGY(v_strategy);
01753 
01754     n = z->stream.avail_out;
01755     err = deflateParams(&z->stream, level, strategy);
01756     z->buf_filled += n - z->stream.avail_out;
01757     while (err == Z_BUF_ERROR) {
01758         rb_warning("deflateParams() returned Z_BUF_ERROR");
01759         zstream_expand_buffer(z);
01760         n = z->stream.avail_out;
01761         err = deflateParams(&z->stream, level, strategy);
01762         z->buf_filled += n - z->stream.avail_out;
01763     }
01764     if (err != Z_OK) {
01765         raise_zlib_error(err, z->stream.msg);
01766     }
01767 
01768     return Qnil;
01769 }
01770 
01771 /*
01772  * Document-method: Zlib::Deflate.set_dictionary
01773  *
01774  * call-seq: set_dictionary(string)
01775  *
01776  * Sets the preset dictionary and returns +string+. This method is available
01777  * just only after Zlib::Deflate.new or Zlib::ZStream#reset method was called.
01778  * See zlib.h for details.
01779  *
01780  * Can raise errors of Z_STREAM_ERROR if a parameter is invalid (such as
01781  * NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if
01782  * the given dictionary doesn't match the expected one (incorrect adler32 value)
01783  *
01784  */
01785 static VALUE
01786 rb_deflate_set_dictionary(VALUE obj, VALUE dic)
01787 {
01788     struct zstream *z = get_zstream(obj);
01789     VALUE src = dic;
01790     int err;
01791 
01792     OBJ_INFECT(obj, dic);
01793     StringValue(src);
01794     err = deflateSetDictionary(&z->stream,
01795                                (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
01796     if (err != Z_OK) {
01797         raise_zlib_error(err, z->stream.msg);
01798     }
01799 
01800     return dic;
01801 }
01802 
01803 
01804 /* ------------------------------------------------------------------------- */
01805 
01806 /*
01807  * Document-class: Zlib::Inflate
01808  *
01809  * Zlib:Inflate is the class for decompressing compressed data.  Unlike
01810  * Zlib::Deflate, an instance of this class is not able to duplicate (clone,
01811  * dup) itself.
01812  */
01813 
01814 static VALUE
01815 rb_inflate_s_allocate(VALUE klass)
01816 {
01817     VALUE inflate = zstream_inflate_new(klass);
01818     rb_ivar_set(inflate, id_dictionaries, rb_hash_new());
01819     return inflate;
01820 }
01821 
01822 /*
01823  * Document-method: Zlib::Inflate.new
01824  *
01825  * call-seq:
01826  *   Zlib::Inflate.new(window_bits = Zlib::MAX_WBITS)
01827  *
01828  * Creates a new inflate stream for decompression.  +window_bits+ sets the
01829  * size of the history buffer and can have the following values:
01830  *
01831  * 0::
01832  *   Have inflate use the window size from the zlib header of the compressed
01833  *   stream.
01834  *
01835  * (8..15)
01836  *   Overrides the window size of the inflate header in the compressed stream.
01837  *   The window size must be greater than or equal to the window size of the
01838  *   compressed stream.
01839  *
01840  * Greater than 15::
01841  *   Add 32 to window_bits to enable zlib and gzip decoding with automatic
01842  *   header detection, or add 16 to decode only the gzip format (a
01843  *   Zlib::DataError will be raised for a non-gzip stream).
01844  *
01845  * (-8..-15)::
01846  *   Enables raw deflate mode which will not generate a check value, and will
01847  *   not look for any check values for comparison at the end of the stream.
01848  *
01849  *   This is for use with other formats that use the deflate compressed data
01850  *   format such as zip which provide their own check values.
01851  *
01852  * == Example
01853  *
01854  *   open "compressed.file" do |compressed_io|
01855  *     inflate = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
01856  *
01857  *     begin
01858  *       open "uncompressed.file", "w+" do |uncompressed_io|
01859  *         uncompressed_io << zi.inflate(compressed_io.read)
01860  *       }
01861  *     ensure
01862  *       zi.close
01863  *     end
01864  *   end
01865  *
01866  */
01867 static VALUE
01868 rb_inflate_initialize(int argc, VALUE *argv, VALUE obj)
01869 {
01870     struct zstream *z;
01871     VALUE wbits;
01872     int err;
01873 
01874     rb_scan_args(argc, argv, "01", &wbits);
01875     Data_Get_Struct(obj, struct zstream, z);
01876 
01877     err = inflateInit2(&z->stream, ARG_WBITS(wbits));
01878     if (err != Z_OK) {
01879         raise_zlib_error(err, z->stream.msg);
01880     }
01881     ZSTREAM_READY(z);
01882 
01883     return obj;
01884 }
01885 
01886 static VALUE
01887 inflate_run(VALUE args)
01888 {
01889     struct zstream *z = (struct zstream*)((VALUE*)args)[0];
01890     VALUE src = ((VALUE*)args)[1];
01891 
01892     zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
01893     zstream_run(z, (Bytef*)"", 0, Z_FINISH);  /* for checking errors */
01894     return zstream_detach_buffer(z);
01895 }
01896 
01897 /*
01898  * Document-method: Zlib::inflate
01899  *
01900  * call-seq:
01901  *   Zlib.inflate(string)
01902  *   Zlib::Inflate.inflate(string)
01903  *
01904  * Decompresses +string+. Raises a Zlib::NeedDict exception if a preset
01905  * dictionary is needed for decompression.
01906  *
01907  * This method is almost equivalent to the following code:
01908  *
01909  *   def inflate(string)
01910  *     zstream = Zlib::Inflate.new
01911  *     buf = zstream.inflate(string)
01912  *     zstream.finish
01913  *     zstream.close
01914  *     buf
01915  *   end
01916  *
01917  * See also Zlib.deflate
01918  *
01919  */
01920 static VALUE
01921 rb_inflate_s_inflate(VALUE obj, VALUE src)
01922 {
01923     struct zstream z;
01924     VALUE dst, args[2];
01925     int err;
01926 
01927     StringValue(src);
01928     zstream_init_inflate(&z);
01929     err = inflateInit(&z.stream);
01930     if (err != Z_OK) {
01931         raise_zlib_error(err, z.stream.msg);
01932     }
01933     ZSTREAM_READY(&z);
01934 
01935     args[0] = (VALUE)&z;
01936     args[1] = src;
01937     dst = rb_ensure(inflate_run, (VALUE)args, zstream_end, (VALUE)&z);
01938 
01939     OBJ_INFECT(dst, src);
01940     return dst;
01941 }
01942 
01943 static void
01944 do_inflate(struct zstream *z, VALUE src)
01945 {
01946     if (NIL_P(src)) {
01947         zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01948         return;
01949     }
01950     StringValue(src);
01951     if (RSTRING_LEN(src) > 0 || z->stream.avail_in > 0) { /* prevent Z_BUF_ERROR */
01952         zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
01953     }
01954 }
01955 
01956 /* Document-method: Zlib::Inflate#add_dictionary
01957  *
01958  * call-seq: add_dictionary(string)
01959  *
01960  * Provide the inflate stream with a dictionary that may be required in the
01961  * future.  Multiple dictionaries may be provided.  The inflate stream will
01962  * automatically choose the correct user-provided dictionary based on the
01963  * stream's required dictionary.
01964  */
01965 static VALUE
01966 rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) {
01967     VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
01968     VALUE checksum = do_checksum(1, &dictionary, adler32);
01969 
01970     rb_hash_aset(dictionaries, checksum, dictionary);
01971 
01972     return obj;
01973 }
01974 
01975 /*
01976  * Document-method: Zlib::Inflate#inflate
01977  *
01978  * call-seq:
01979  *   inflate(deflate_string)                 -> String
01980  *   inflate(deflate_string) { |chunk| ... } -> nil
01981  *
01982  * Inputs +deflate_string+ into the inflate stream and returns the output from
01983  * the stream.  Calling this method, both the input and the output buffer of
01984  * the stream are flushed.  If string is +nil+, this method finishes the
01985  * stream, just like Zlib::ZStream#finish.
01986  *
01987  * If a block is given consecutive inflated chunks from the +deflate_string+
01988  * are yielded to the block and +nil+ is returned.
01989  *
01990  * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
01991  * decompress.  Set the dictionary by Zlib::Inflate#set_dictionary and then
01992  * call this method again with an empty string to flush the stream:
01993  *
01994  *   inflater = Zlib::Inflate.new
01995  *
01996  *   begin
01997  *     out = inflater.inflate compressed
01998  *   rescue Zlib::NeedDict
01999  *     # ensure the dictionary matches the stream's required dictionary
02000  *     raise unless inflater.adler == Zlib.adler32(dictionary)
02001  *
02002  *     inflater.set_dictionary dictionary
02003  *     inflater.inflate ''
02004  *   end
02005  *
02006  *   # ...
02007  *
02008  *   inflater.close
02009  *
02010  * See also Zlib::Inflate.new
02011  */
02012 static VALUE
02013 rb_inflate_inflate(VALUE obj, VALUE src)
02014 {
02015     struct zstream *z = get_zstream(obj);
02016     VALUE dst;
02017 
02018     OBJ_INFECT(obj, src);
02019 
02020     if (ZSTREAM_IS_FINISHED(z)) {
02021         if (NIL_P(src)) {
02022             dst = zstream_detach_buffer(z);
02023         }
02024         else {
02025             StringValue(src);
02026             zstream_append_buffer2(z, src);
02027             dst = rb_str_new(0, 0);
02028             OBJ_INFECT(dst, obj);
02029         }
02030     }
02031     else {
02032         do_inflate(z, src);
02033         dst = zstream_detach_buffer(z);
02034         if (ZSTREAM_IS_FINISHED(z)) {
02035             zstream_passthrough_input(z);
02036         }
02037     }
02038 
02039     return dst;
02040 }
02041 
02042 /*
02043  * call-seq: << string
02044  *
02045  * Inputs +string+ into the inflate stream just like Zlib::Inflate#inflate, but
02046  * returns the Zlib::Inflate object itself.  The output from the stream is
02047  * preserved in output buffer.
02048  */
02049 static VALUE
02050 rb_inflate_addstr(VALUE obj, VALUE src)
02051 {
02052     struct zstream *z = get_zstream(obj);
02053 
02054     OBJ_INFECT(obj, src);
02055 
02056     if (ZSTREAM_IS_FINISHED(z)) {
02057         if (!NIL_P(src)) {
02058             StringValue(src);
02059             zstream_append_buffer2(z, src);
02060         }
02061     }
02062     else {
02063         do_inflate(z, src);
02064         if (ZSTREAM_IS_FINISHED(z)) {
02065             zstream_passthrough_input(z);
02066         }
02067     }
02068 
02069     return obj;
02070 }
02071 
02072 /*
02073  * call-seq: sync(string)
02074  *
02075  * Inputs +string+ into the end of input buffer and skips data until a full
02076  * flush point can be found.  If the point is found in the buffer, this method
02077  * flushes the buffer and returns false.  Otherwise it returns +true+ and the
02078  * following data of full flush point is preserved in the buffer.
02079  */
02080 static VALUE
02081 rb_inflate_sync(VALUE obj, VALUE src)
02082 {
02083     struct zstream *z = get_zstream(obj);
02084 
02085     OBJ_INFECT(obj, src);
02086     StringValue(src);
02087     return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
02088 }
02089 
02090 /*
02091  * Quoted verbatim from original documentation:
02092  *
02093  *   What is this?
02094  *
02095  * <tt>:)</tt>
02096  */
02097 static VALUE
02098 rb_inflate_sync_point_p(VALUE obj)
02099 {
02100     struct zstream *z = get_zstream(obj);
02101     int err;
02102 
02103     err = inflateSyncPoint(&z->stream);
02104     if (err == 1) {
02105         return Qtrue;
02106     }
02107     if (err != Z_OK) {
02108         raise_zlib_error(err, z->stream.msg);
02109     }
02110     return Qfalse;
02111 }
02112 
02113 /*
02114  * Document-method: Zlib::Inflate#set_dictionary
02115  *
02116  * Sets the preset dictionary and returns +string+.  This method is available just
02117  * only after a Zlib::NeedDict exception was raised.  See zlib.h for details.
02118  *
02119  */
02120 static VALUE
02121 rb_inflate_set_dictionary(VALUE obj, VALUE dic)
02122 {
02123     struct zstream *z = get_zstream(obj);
02124     VALUE src = dic;
02125     int err;
02126 
02127     OBJ_INFECT(obj, dic);
02128     StringValue(src);
02129     err = inflateSetDictionary(&z->stream,
02130                                (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
02131     if (err != Z_OK) {
02132         raise_zlib_error(err, z->stream.msg);
02133     }
02134 
02135     return dic;
02136 }
02137 
02138 
02139 
02140 #if GZIP_SUPPORT
02141 
02142 /* NOTE: Features for gzip files of Ruby/zlib are written from scratch
02143  *       and using undocumented feature of zlib, negative wbits.
02144  *       I don't think gzFile APIs of zlib are good for Ruby.
02145  */
02146 
02147 /*------- .gz file header --------*/
02148 
02149 #define GZ_MAGIC1             0x1f
02150 #define GZ_MAGIC2             0x8b
02151 #define GZ_METHOD_DEFLATE     8
02152 #define GZ_FLAG_MULTIPART     0x2
02153 #define GZ_FLAG_EXTRA         0x4
02154 #define GZ_FLAG_ORIG_NAME     0x8
02155 #define GZ_FLAG_COMMENT       0x10
02156 #define GZ_FLAG_ENCRYPT       0x20
02157 #define GZ_FLAG_UNKNOWN_MASK  0xc0
02158 
02159 #define GZ_EXTRAFLAG_FAST     0x4
02160 #define GZ_EXTRAFLAG_SLOW     0x2
02161 
02162 /* from zutil.h */
02163 #define OS_MSDOS    0x00
02164 #define OS_AMIGA    0x01
02165 #define OS_VMS      0x02
02166 #define OS_UNIX     0x03
02167 #define OS_ATARI    0x05
02168 #define OS_OS2      0x06
02169 #define OS_MACOS    0x07
02170 #define OS_TOPS20   0x0a
02171 #define OS_WIN32    0x0b
02172 
02173 #define OS_VMCMS    0x04
02174 #define OS_ZSYSTEM  0x08
02175 #define OS_CPM      0x09
02176 #define OS_QDOS     0x0c
02177 #define OS_RISCOS   0x0d
02178 #define OS_UNKNOWN  0xff
02179 
02180 #ifndef OS_CODE
02181 #define OS_CODE  OS_UNIX
02182 #endif
02183 
02184 static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
02185 static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
02186 
02187 
02188 
02189 /*-------- gzfile internal APIs --------*/
02190 
02191 struct gzfile {
02192     struct zstream z;
02193     VALUE io;
02194     int level;
02195     time_t mtime;       /* for header */
02196     int os_code;        /* for header */
02197     VALUE orig_name;    /* for header; must be a String */
02198     VALUE comment;      /* for header; must be a String */
02199     unsigned long crc;
02200     int lineno;
02201     long ungetc;
02202     void (*end)(struct gzfile *);
02203     rb_encoding *enc;
02204     rb_encoding *enc2;
02205     rb_econv_t *ec;
02206     int ecflags;
02207     VALUE ecopts;
02208     char *cbuf;
02209     VALUE path;
02210 };
02211 #define GZFILE_CBUF_CAPA 10
02212 
02213 #define GZFILE_FLAG_SYNC             ZSTREAM_FLAG_UNUSED
02214 #define GZFILE_FLAG_HEADER_FINISHED  (ZSTREAM_FLAG_UNUSED << 1)
02215 #define GZFILE_FLAG_FOOTER_FINISHED  (ZSTREAM_FLAG_UNUSED << 2)
02216 
02217 #define GZFILE_IS_FINISHED(gz) \
02218     (ZSTREAM_IS_FINISHED(&(gz)->z) && (gz)->z.buf_filled == 0)
02219 
02220 #define GZFILE_READ_SIZE  2048
02221 
02222 
02223 static void
02224 gzfile_mark(struct gzfile *gz)
02225 {
02226     rb_gc_mark(gz->io);
02227     rb_gc_mark(gz->orig_name);
02228     rb_gc_mark(gz->comment);
02229     zstream_mark(&gz->z);
02230     rb_gc_mark(gz->ecopts);
02231     rb_gc_mark(gz->path);
02232 }
02233 
02234 static void
02235 gzfile_free(struct gzfile *gz)
02236 {
02237     struct zstream *z = &gz->z;
02238 
02239     if (ZSTREAM_IS_READY(z)) {
02240         if (z->func == &deflate_funcs) {
02241             finalizer_warn("Zlib::GzipWriter object must be closed explicitly.");
02242         }
02243         zstream_finalize(z);
02244     }
02245     if (gz->cbuf) {
02246         xfree(gz->cbuf);
02247     }
02248     xfree(gz);
02249 }
02250 
02251 static VALUE
02252 gzfile_new(klass, funcs, endfunc)
02253     VALUE klass;
02254     const struct zstream_funcs *funcs;
02255     void (*endfunc)(struct gzfile *);
02256 {
02257     VALUE obj;
02258     struct gzfile *gz;
02259 
02260     obj = Data_Make_Struct(klass, struct gzfile, gzfile_mark, gzfile_free, gz);
02261     zstream_init(&gz->z, funcs);
02262     gz->z.flags |= ZSTREAM_FLAG_GZFILE;
02263     gz->io = Qnil;
02264     gz->level = 0;
02265     gz->mtime = 0;
02266     gz->os_code = OS_CODE;
02267     gz->orig_name = Qnil;
02268     gz->comment = Qnil;
02269     gz->crc = crc32(0, Z_NULL, 0);
02270     gz->lineno = 0;
02271     gz->ungetc = 0;
02272     gz->end = endfunc;
02273     gz->enc = rb_default_external_encoding();
02274     gz->enc2 = 0;
02275     gz->ec = NULL;
02276     gz->ecflags = 0;
02277     gz->ecopts = Qnil;
02278     gz->cbuf = 0;
02279     gz->path = Qnil;
02280 
02281     return obj;
02282 }
02283 
02284 #define gzfile_writer_new(gz) gzfile_new((gz),&deflate_funcs,gzfile_writer_end)
02285 #define gzfile_reader_new(gz) gzfile_new((gz),&inflate_funcs,gzfile_reader_end)
02286 
02287 static void
02288 gzfile_reset(struct gzfile *gz)
02289 {
02290     zstream_reset(&gz->z);
02291     gz->crc = crc32(0, Z_NULL, 0);
02292     gz->lineno = 0;
02293     gz->ungetc = 0;
02294     if (gz->ec) {
02295         rb_econv_close(gz->ec);
02296         gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
02297                                     gz->ecflags, gz->ecopts);
02298     }
02299 }
02300 
02301 static void
02302 gzfile_close(struct gzfile *gz, int closeflag)
02303 {
02304     VALUE io = gz->io;
02305 
02306     gz->end(gz);
02307     gz->io = Qnil;
02308     gz->orig_name = Qnil;
02309     gz->comment = Qnil;
02310     if (closeflag && rb_respond_to(io, id_close)) {
02311         rb_funcall(io, id_close, 0);
02312     }
02313 }
02314 
02315 static void
02316 gzfile_write_raw(struct gzfile *gz)
02317 {
02318     VALUE str;
02319 
02320     if (gz->z.buf_filled > 0) {
02321         str = zstream_detach_buffer(&gz->z);
02322         OBJ_TAINT(str);  /* for safe */
02323         rb_funcall(gz->io, id_write, 1, str);
02324         if ((gz->z.flags & GZFILE_FLAG_SYNC)
02325             && rb_respond_to(gz->io, id_flush))
02326             rb_funcall(gz->io, id_flush, 0);
02327     }
02328 }
02329 
02330 static VALUE
02331 gzfile_read_raw_partial(VALUE arg)
02332 {
02333     struct gzfile *gz = (struct gzfile*)arg;
02334     VALUE str;
02335 
02336     str = rb_funcall(gz->io, id_readpartial, 1, INT2FIX(GZFILE_READ_SIZE));
02337     Check_Type(str, T_STRING);
02338     return str;
02339 }
02340 
02341 static VALUE
02342 gzfile_read_raw_rescue(VALUE arg)
02343 {
02344     struct gzfile *gz = (struct gzfile*)arg;
02345     VALUE str = Qnil;
02346     if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
02347         str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
02348         if (!NIL_P(str)) {
02349             Check_Type(str, T_STRING);
02350         }
02351     }
02352     return str; /* return nil when EOFError */
02353 }
02354 
02355 static VALUE
02356 gzfile_read_raw(struct gzfile *gz)
02357 {
02358     return rb_rescue2(gzfile_read_raw_partial, (VALUE)gz,
02359                       gzfile_read_raw_rescue, (VALUE)gz,
02360                       rb_eEOFError, rb_eNoMethodError, (VALUE)0);
02361 }
02362 
02363 static int
02364 gzfile_read_raw_ensure(struct gzfile *gz, long size)
02365 {
02366     VALUE str;
02367 
02368     while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
02369         str = gzfile_read_raw(gz);
02370         if (NIL_P(str)) return 0;
02371         zstream_append_input2(&gz->z, str);
02372     }
02373     return 1;
02374 }
02375 
02376 static char *
02377 gzfile_read_raw_until_zero(struct gzfile *gz, long offset)
02378 {
02379     VALUE str;
02380     char *p;
02381 
02382     for (;;) {
02383         p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
02384                    RSTRING_LEN(gz->z.input) - offset);
02385         if (p) break;
02386         str = gzfile_read_raw(gz);
02387         if (NIL_P(str)) {
02388             rb_raise(cGzError, "unexpected end of file");
02389         }
02390         offset = RSTRING_LEN(gz->z.input);
02391         zstream_append_input2(&gz->z, str);
02392     }
02393     return p;
02394 }
02395 
02396 static unsigned int
02397 gzfile_get16(const unsigned char *src)
02398 {
02399     unsigned int n;
02400     n  = *(src++) & 0xff;
02401     n |= (*(src++) & 0xff) << 8;
02402     return n;
02403 }
02404 
02405 static unsigned long
02406 gzfile_get32(const unsigned char *src)
02407 {
02408     unsigned long n;
02409     n  = *(src++) & 0xff;
02410     n |= (*(src++) & 0xff) << 8;
02411     n |= (*(src++) & 0xff) << 16;
02412     n |= (*(src++) & 0xffU) << 24;
02413     return n;
02414 }
02415 
02416 static void
02417 gzfile_set32(unsigned long n, unsigned char *dst)
02418 {
02419     *(dst++) = n & 0xff;
02420     *(dst++) = (n >> 8) & 0xff;
02421     *(dst++) = (n >> 16) & 0xff;
02422     *dst     = (n >> 24) & 0xff;
02423 }
02424 
02425 static void
02426 gzfile_raise(struct gzfile *gz, VALUE klass, const char *message)
02427 {
02428     VALUE exc = rb_exc_new2(klass, message);
02429     if (!NIL_P(gz->z.input)) {
02430         rb_ivar_set(exc, id_input, rb_str_resurrect(gz->z.input));
02431     }
02432     rb_exc_raise(exc);
02433 }
02434 
02435 /*
02436  * Document-method: Zlib::GzipFile::Error#inspect
02437  *
02438  * Constructs a String of the GzipFile Error
02439  */
02440 static VALUE
02441 gzfile_error_inspect(VALUE error)
02442 {
02443     VALUE str = rb_call_super(0, 0);
02444     VALUE input = rb_attr_get(error, id_input);
02445 
02446     if (!NIL_P(input)) {
02447         rb_str_resize(str, RSTRING_LEN(str)-1);
02448         rb_str_cat2(str, ", input=");
02449         rb_str_append(str, rb_str_inspect(input));
02450         rb_str_cat2(str, ">");
02451     }
02452     return str;
02453 }
02454 
02455 static void
02456 gzfile_make_header(struct gzfile *gz)
02457 {
02458     Bytef buf[10];  /* the size of gzip header */
02459     unsigned char flags = 0, extraflags = 0;
02460 
02461     if (!NIL_P(gz->orig_name)) {
02462         flags |= GZ_FLAG_ORIG_NAME;
02463     }
02464     if (!NIL_P(gz->comment)) {
02465         flags |= GZ_FLAG_COMMENT;
02466     }
02467     if (gz->mtime == 0) {
02468         gz->mtime = time(0);
02469     }
02470 
02471     if (gz->level == Z_BEST_SPEED) {
02472         extraflags |= GZ_EXTRAFLAG_FAST;
02473     }
02474     else if (gz->level == Z_BEST_COMPRESSION) {
02475         extraflags |= GZ_EXTRAFLAG_SLOW;
02476     }
02477 
02478     buf[0] = GZ_MAGIC1;
02479     buf[1] = GZ_MAGIC2;
02480     buf[2] = GZ_METHOD_DEFLATE;
02481     buf[3] = flags;
02482     gzfile_set32((unsigned long)gz->mtime, &buf[4]);
02483     buf[8] = extraflags;
02484     buf[9] = gz->os_code;
02485     zstream_append_buffer(&gz->z, buf, sizeof(buf));
02486 
02487     if (!NIL_P(gz->orig_name)) {
02488         zstream_append_buffer2(&gz->z, gz->orig_name);
02489         zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
02490     }
02491     if (!NIL_P(gz->comment)) {
02492         zstream_append_buffer2(&gz->z, gz->comment);
02493         zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
02494     }
02495 
02496     gz->z.flags |= GZFILE_FLAG_HEADER_FINISHED;
02497 }
02498 
02499 static void
02500 gzfile_make_footer(struct gzfile *gz)
02501 {
02502     Bytef buf[8];  /* 8 is the size of gzip footer */
02503 
02504     gzfile_set32(gz->crc, buf);
02505     gzfile_set32(gz->z.stream.total_in, &buf[4]);
02506     zstream_append_buffer(&gz->z, buf, sizeof(buf));
02507     gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
02508 }
02509 
02510 static void
02511 gzfile_read_header(struct gzfile *gz)
02512 {
02513     const unsigned char *head;
02514     long len;
02515     char flags, *p;
02516 
02517     if (!gzfile_read_raw_ensure(gz, 10)) {  /* 10 is the size of gzip header */
02518         gzfile_raise(gz, cGzError, "not in gzip format");
02519     }
02520 
02521     head = (unsigned char*)RSTRING_PTR(gz->z.input);
02522 
02523     if (head[0] != GZ_MAGIC1 || head[1] != GZ_MAGIC2) {
02524         gzfile_raise(gz, cGzError, "not in gzip format");
02525     }
02526     if (head[2] != GZ_METHOD_DEFLATE) {
02527         rb_raise(cGzError, "unsupported compression method %d", head[2]);
02528     }
02529 
02530     flags = head[3];
02531     if (flags & GZ_FLAG_MULTIPART) {
02532         rb_raise(cGzError, "multi-part gzip file is not supported");
02533     }
02534     else if (flags & GZ_FLAG_ENCRYPT) {
02535         rb_raise(cGzError, "encrypted gzip file is not supported");
02536     }
02537     else if (flags & GZ_FLAG_UNKNOWN_MASK) {
02538         rb_raise(cGzError, "unknown flags 0x%02x", flags);
02539     }
02540 
02541     if (head[8] & GZ_EXTRAFLAG_FAST) {
02542         gz->level = Z_BEST_SPEED;
02543     }
02544     else if (head[8] & GZ_EXTRAFLAG_SLOW) {
02545         gz->level = Z_BEST_COMPRESSION;
02546     }
02547     else {
02548         gz->level = Z_DEFAULT_COMPRESSION;
02549     }
02550 
02551     gz->mtime = gzfile_get32(&head[4]);
02552     gz->os_code = head[9];
02553     zstream_discard_input(&gz->z, 10);
02554 
02555     if (flags & GZ_FLAG_EXTRA) {
02556         if (!gzfile_read_raw_ensure(gz, 2)) {
02557             rb_raise(cGzError, "unexpected end of file");
02558         }
02559         len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
02560         if (!gzfile_read_raw_ensure(gz, 2 + len)) {
02561             rb_raise(cGzError, "unexpected end of file");
02562         }
02563         zstream_discard_input(&gz->z, 2 + len);
02564     }
02565     if (flags & GZ_FLAG_ORIG_NAME) {
02566         if (!gzfile_read_raw_ensure(gz, 1)) {
02567             rb_raise(cGzError, "unexpected end of file");
02568         }
02569         p = gzfile_read_raw_until_zero(gz, 0);
02570         len = p - RSTRING_PTR(gz->z.input);
02571         gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len);
02572         OBJ_TAINT(gz->orig_name);  /* for safe */
02573         zstream_discard_input(&gz->z, len + 1);
02574     }
02575     if (flags & GZ_FLAG_COMMENT) {
02576         if (!gzfile_read_raw_ensure(gz, 1)) {
02577             rb_raise(cGzError, "unexpected end of file");
02578         }
02579         p = gzfile_read_raw_until_zero(gz, 0);
02580         len = p - RSTRING_PTR(gz->z.input);
02581         gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
02582         OBJ_TAINT(gz->comment);  /* for safe */
02583         zstream_discard_input(&gz->z, len + 1);
02584     }
02585 
02586     if (gz->z.input != Qnil && RSTRING_LEN(gz->z.input) > 0) {
02587         zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH);
02588     }
02589 }
02590 
02591 static void
02592 gzfile_check_footer(struct gzfile *gz)
02593 {
02594     unsigned long crc, length;
02595 
02596     gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
02597 
02598     if (!gzfile_read_raw_ensure(gz, 8)) { /* 8 is the size of gzip footer */
02599         gzfile_raise(gz, cNoFooter, "footer is not found");
02600     }
02601 
02602     crc = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input));
02603     length = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input) + 4);
02604 
02605     gz->z.stream.total_in += 8;  /* to rewind correctly */
02606     zstream_discard_input(&gz->z, 8);
02607 
02608     if (gz->crc != crc) {
02609         rb_raise(cCRCError, "invalid compressed data -- crc error");
02610     }
02611     if ((uint32_t)gz->z.stream.total_out != length) {
02612         rb_raise(cLengthError, "invalid compressed data -- length error");
02613     }
02614 }
02615 
02616 static void
02617 gzfile_write(struct gzfile *gz, Bytef *str, long len)
02618 {
02619     if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
02620         gzfile_make_header(gz);
02621     }
02622 
02623     if (len > 0 || (gz->z.flags & GZFILE_FLAG_SYNC)) {
02624         gz->crc = checksum_long(crc32, gz->crc, str, len);
02625         zstream_run(&gz->z, str, len, (gz->z.flags & GZFILE_FLAG_SYNC)
02626                     ? Z_SYNC_FLUSH : Z_NO_FLUSH);
02627     }
02628     gzfile_write_raw(gz);
02629 }
02630 
02631 static long
02632 gzfile_read_more(struct gzfile *gz)
02633 {
02634     volatile VALUE str;
02635 
02636     while (!ZSTREAM_IS_FINISHED(&gz->z)) {
02637         str = gzfile_read_raw(gz);
02638         if (NIL_P(str)) {
02639             if (!ZSTREAM_IS_FINISHED(&gz->z)) {
02640                 rb_raise(cGzError, "unexpected end of file");
02641             }
02642             break;
02643         }
02644         if (RSTRING_LEN(str) > 0) { /* prevent Z_BUF_ERROR */
02645             zstream_run(&gz->z, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str),
02646                         Z_SYNC_FLUSH);
02647         }
02648         if (gz->z.buf_filled > 0) break;
02649     }
02650     return gz->z.buf_filled;
02651 }
02652 
02653 static void
02654 gzfile_calc_crc(struct gzfile *gz, VALUE str)
02655 {
02656     if (RSTRING_LEN(str) <= gz->ungetc) {
02657         gz->ungetc -= RSTRING_LEN(str);
02658     }
02659     else {
02660         gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
02661                         RSTRING_LEN(str) - gz->ungetc);
02662         gz->ungetc = 0;
02663     }
02664 }
02665 
02666 static VALUE
02667 gzfile_newstr(struct gzfile *gz, VALUE str)
02668 {
02669     if (!gz->enc2) {
02670         rb_enc_associate(str, gz->enc);
02671         OBJ_TAINT(str);  /* for safe */
02672         return str;
02673     }
02674     if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
02675         str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
02676         rb_enc_associate(str, gz->enc);
02677         OBJ_TAINT(str);
02678         return str;
02679     }
02680     return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
02681                                 gz->ecflags, gz->ecopts);
02682 }
02683 
02684 static long
02685 gzfile_fill(struct gzfile *gz, long len)
02686 {
02687     if (len < 0)
02688         rb_raise(rb_eArgError, "negative length %ld given", len);
02689     if (len == 0)
02690         return 0;
02691     while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
02692         gzfile_read_more(gz);
02693     }
02694     if (GZFILE_IS_FINISHED(gz)) {
02695         if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02696             gzfile_check_footer(gz);
02697         }
02698         return -1;
02699     }
02700     return len < gz->z.buf_filled ? len : gz->z.buf_filled;
02701 }
02702 
02703 static VALUE
02704 gzfile_read(struct gzfile *gz, long len)
02705 {
02706     VALUE dst;
02707 
02708     len = gzfile_fill(gz, len);
02709     if (len == 0) return rb_str_new(0, 0);
02710     if (len < 0) return Qnil;
02711     dst = zstream_shift_buffer(&gz->z, len);
02712     if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
02713     return dst;
02714 }
02715 
02716 static VALUE
02717 gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
02718 {
02719     VALUE dst;
02720 
02721     if (len < 0)
02722         rb_raise(rb_eArgError, "negative length %ld given", len);
02723 
02724     if (!NIL_P(outbuf))
02725         OBJ_TAINT(outbuf);
02726 
02727     if (len == 0) {
02728         if (NIL_P(outbuf))
02729             return rb_str_new(0, 0);
02730         else {
02731             rb_str_resize(outbuf, 0);
02732             return outbuf;
02733         }
02734     }
02735     while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled == 0) {
02736         gzfile_read_more(gz);
02737     }
02738     if (GZFILE_IS_FINISHED(gz)) {
02739         if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02740             gzfile_check_footer(gz);
02741         }
02742         if (!NIL_P(outbuf))
02743             rb_str_resize(outbuf, 0);
02744         rb_raise(rb_eEOFError, "end of file reached");
02745     }
02746 
02747     dst = zstream_shift_buffer(&gz->z, len);
02748     gzfile_calc_crc(gz, dst);
02749 
02750     if (!NIL_P(outbuf)) {
02751         rb_str_resize(outbuf, RSTRING_LEN(dst));
02752         memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
02753         dst = outbuf;
02754     }
02755     OBJ_TAINT(dst);  /* for safe */
02756     return dst;
02757 }
02758 
02759 static VALUE
02760 gzfile_read_all(struct gzfile *gz)
02761 {
02762     VALUE dst;
02763 
02764     while (!ZSTREAM_IS_FINISHED(&gz->z)) {
02765         gzfile_read_more(gz);
02766     }
02767     if (GZFILE_IS_FINISHED(gz)) {
02768         if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02769             gzfile_check_footer(gz);
02770         }
02771         return rb_str_new(0, 0);
02772     }
02773 
02774     dst = zstream_detach_buffer(&gz->z);
02775     if (NIL_P(dst)) return dst;
02776     gzfile_calc_crc(gz, dst);
02777     OBJ_TAINT(dst);
02778     return gzfile_newstr(gz, dst);
02779 }
02780 
02781 static VALUE
02782 gzfile_getc(struct gzfile *gz)
02783 {
02784     VALUE buf, dst = 0;
02785     int len;
02786 
02787     len = rb_enc_mbmaxlen(gz->enc);
02788     while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
02789         gzfile_read_more(gz);
02790     }
02791     if (GZFILE_IS_FINISHED(gz)) {
02792         if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02793             gzfile_check_footer(gz);
02794         }
02795         return Qnil;
02796     }
02797 
02798     if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
02799         const unsigned char *ss, *sp, *se;
02800         unsigned char *ds, *dp, *de;
02801 
02802         if (!gz->cbuf) {
02803             gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA);
02804         }
02805         ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
02806         se = sp + gz->z.buf_filled;
02807         ds = dp = (unsigned char *)gz->cbuf;
02808         de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
02809         (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
02810         rb_econv_check_error(gz->ec);
02811         dst = zstream_shift_buffer(&gz->z, sp - ss);
02812         gzfile_calc_crc(gz, dst);
02813         dst = rb_str_new(gz->cbuf, dp - ds);
02814         rb_enc_associate(dst, gz->enc);
02815         OBJ_TAINT(dst);
02816         return dst;
02817     }
02818     else {
02819         buf = gz->z.buf;
02820         len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
02821         dst = gzfile_read(gz, len);
02822         if (NIL_P(dst)) return dst;
02823         return gzfile_newstr(gz, dst);
02824     }
02825 }
02826 
02827 static void
02828 gzfile_ungets(struct gzfile *gz, const Bytef *b, long len)
02829 {
02830     zstream_buffer_ungets(&gz->z, b, len);
02831     gz->ungetc+=len;
02832 }
02833 
02834 static void
02835 gzfile_ungetbyte(struct gzfile *gz, int c)
02836 {
02837     zstream_buffer_ungetbyte(&gz->z, c);
02838     gz->ungetc++;
02839 }
02840 
02841 static VALUE
02842 gzfile_writer_end_run(VALUE arg)
02843 {
02844     struct gzfile *gz = (struct gzfile *)arg;
02845 
02846     if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
02847         gzfile_make_header(gz);
02848     }
02849 
02850     zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
02851     gzfile_make_footer(gz);
02852     gzfile_write_raw(gz);
02853 
02854     return Qnil;
02855 }
02856 
02857 static void
02858 gzfile_writer_end(struct gzfile *gz)
02859 {
02860     if (ZSTREAM_IS_CLOSING(&gz->z)) return;
02861     gz->z.flags |= ZSTREAM_FLAG_CLOSING;
02862 
02863     rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
02864 }
02865 
02866 static VALUE
02867 gzfile_reader_end_run(VALUE arg)
02868 {
02869     struct gzfile *gz = (struct gzfile *)arg;
02870 
02871     if (GZFILE_IS_FINISHED(gz)
02872         && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02873         gzfile_check_footer(gz);
02874     }
02875 
02876     return Qnil;
02877 }
02878 
02879 static void
02880 gzfile_reader_end(struct gzfile *gz)
02881 {
02882     if (ZSTREAM_IS_CLOSING(&gz->z)) return;
02883     gz->z.flags |= ZSTREAM_FLAG_CLOSING;
02884 
02885     rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
02886 }
02887 
02888 static void
02889 gzfile_reader_rewind(struct gzfile *gz)
02890 {
02891     long n;
02892 
02893     n = gz->z.stream.total_in;
02894     if (!NIL_P(gz->z.input)) {
02895         n += RSTRING_LEN(gz->z.input);
02896     }
02897 
02898     rb_funcall(gz->io, id_seek, 2, rb_int2inum(-n), INT2FIX(1));
02899     gzfile_reset(gz);
02900 }
02901 
02902 static VALUE
02903 gzfile_reader_get_unused(struct gzfile *gz)
02904 {
02905     VALUE str;
02906 
02907     if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
02908     if (!GZFILE_IS_FINISHED(gz)) return Qnil;
02909     if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02910         gzfile_check_footer(gz);
02911     }
02912     if (NIL_P(gz->z.input)) return Qnil;
02913 
02914     str = rb_str_resurrect(gz->z.input);
02915     OBJ_TAINT(str);  /* for safe */
02916     return str;
02917 }
02918 
02919 static struct gzfile *
02920 get_gzfile(VALUE obj)
02921 {
02922     struct gzfile *gz;
02923 
02924     Data_Get_Struct(obj, struct gzfile, gz);
02925     if (!ZSTREAM_IS_READY(&gz->z)) {
02926         rb_raise(cGzError, "closed gzip stream");
02927     }
02928     return gz;
02929 }
02930 
02931 
02932 /* ------------------------------------------------------------------------- */
02933 
02934 /*
02935  * Document-class: Zlib::GzipFile
02936  *
02937  * Zlib::GzipFile is an abstract class for handling a gzip formatted
02938  * compressed file. The operations are defined in the subclasses,
02939  * Zlib::GzipReader for reading, and Zlib::GzipWriter for writing.
02940  *
02941  * GzipReader should be used by associating an IO, or IO-like, object.
02942  *
02943  * == Method Catalogue
02944  *
02945  * - ::wrap
02946  * - ::open (Zlib::GzipReader::open and Zlib::GzipWriter::open)
02947  * - #close
02948  * - #closed?
02949  * - #comment
02950  * - comment= (Zlib::GzipWriter#comment=)
02951  * - #crc
02952  * - eof? (Zlib::GzipReader#eof?)
02953  * - #finish
02954  * - #level
02955  * - lineno (Zlib::GzipReader#lineno)
02956  * - lineno= (Zlib::GzipReader#lineno=)
02957  * - #mtime
02958  * - mtime= (Zlib::GzipWriter#mtime=)
02959  * - #orig_name
02960  * - orig_name (Zlib::GzipWriter#orig_name=)
02961  * - #os_code
02962  * - path (when the underlying IO supports #path)
02963  * - #sync
02964  * - #sync=
02965  * - #to_io
02966  *
02967  * (due to internal structure, documentation may appear under Zlib::GzipReader
02968  * or Zlib::GzipWriter)
02969  */
02970 
02971 
02972 typedef struct {
02973     int argc;
02974     VALUE *argv;
02975     VALUE klass;
02976 } new_wrap_arg_t;
02977 
02978 static VALUE
02979 new_wrap(VALUE tmp)
02980 {
02981     new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp;
02982     return rb_class_new_instance(arg->argc, arg->argv, arg->klass);
02983 }
02984 
02985 static VALUE
02986 gzfile_ensure_close(VALUE obj)
02987 {
02988     struct gzfile *gz;
02989 
02990     Data_Get_Struct(obj, struct gzfile, gz);
02991     if (ZSTREAM_IS_READY(&gz->z)) {
02992         gzfile_close(gz, 1);
02993     }
02994     return Qnil;
02995 }
02996 
02997 static VALUE
02998 gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
02999 {
03000     VALUE obj;
03001 
03002     if (close_io_on_error) {
03003         int state = 0;
03004         new_wrap_arg_t arg;
03005         arg.argc = argc;
03006         arg.argv = argv;
03007         arg.klass = klass;
03008         obj = rb_protect(new_wrap, (VALUE)&arg, &state);
03009         if (state) {
03010             rb_io_close(argv[0]);
03011             rb_jump_tag(state);
03012         }
03013     }
03014     else {
03015         obj = rb_class_new_instance(argc, argv, klass);
03016     }
03017 
03018     if (rb_block_given_p()) {
03019         return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
03020     }
03021     else {
03022         return obj;
03023     }
03024 }
03025 
03026 /*
03027  * Document-method: Zlib::GzipFile.wrap
03028  *
03029  * call-seq:
03030  *   Zlib::GzipReader.wrap(io, ...) { |gz| ... }
03031  *   Zlib::GzipWriter.wrap(io, ...) { |gz| ... }
03032  *
03033  * Creates a GzipReader or GzipWriter associated with +io+, passing in any
03034  * necessary extra options, and executes the block with the newly created
03035  * object just like File.open.
03036  *
03037  * The GzipFile object will be closed automatically after executing the block.
03038  * If you want to keep the associated IO object open, you may call
03039  * Zlib::GzipFile#finish method in the block.
03040  */
03041 static VALUE
03042 rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
03043 {
03044     return gzfile_wrap(argc, argv, klass, 0);
03045 }
03046 
03047 /*
03048  * Document-method: Zlib::GzipFile.open
03049  *
03050  * See Zlib::GzipReader#open and Zlib::GzipWriter#open.
03051  */
03052 static VALUE
03053 gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
03054 {
03055     VALUE io, filename;
03056 
03057     if (argc < 1) {
03058         rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
03059     }
03060     filename = argv[0];
03061     io = rb_file_open_str(filename, mode);
03062     argv[0] = io;
03063     return gzfile_wrap(argc, argv, klass, 1);
03064 }
03065 
03066 /*
03067  * Document-method: Zlib::GzipFile#to_io
03068  *
03069  * Same as IO.
03070  */
03071 static VALUE
03072 rb_gzfile_to_io(VALUE obj)
03073 {
03074     return get_gzfile(obj)->io;
03075 }
03076 
03077 /*
03078  * Document-method: Zlib::GzipFile#crc
03079  *
03080  * Returns CRC value of the uncompressed data.
03081  */
03082 static VALUE
03083 rb_gzfile_crc(VALUE obj)
03084 {
03085     return rb_uint2inum(get_gzfile(obj)->crc);
03086 }
03087 
03088 /*
03089  * Document-method: Zlib::GzipFile#mtime
03090  *
03091  * Returns last modification time recorded in the gzip file header.
03092  */
03093 static VALUE
03094 rb_gzfile_mtime(VALUE obj)
03095 {
03096     return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
03097 }
03098 
03099 /*
03100  * Document-method: Zlib::GzipFile#level
03101  *
03102  * Returns compression level.
03103  */
03104 static VALUE
03105 rb_gzfile_level(VALUE obj)
03106 {
03107     return INT2FIX(get_gzfile(obj)->level);
03108 }
03109 
03110 /*
03111  * Document-method: Zlib::GzipFile#os_code
03112  *
03113  * Returns OS code number recorded in the gzip file header.
03114  */
03115 static VALUE
03116 rb_gzfile_os_code(VALUE obj)
03117 {
03118     return INT2FIX(get_gzfile(obj)->os_code);
03119 }
03120 
03121 /*
03122  * Document-method: Zlib::GzipFile#orig_name
03123  *
03124  * Returns original filename recorded in the gzip file header, or +nil+ if
03125  * original filename is not present.
03126  */
03127 static VALUE
03128 rb_gzfile_orig_name(VALUE obj)
03129 {
03130     VALUE str = get_gzfile(obj)->orig_name;
03131     if (!NIL_P(str)) {
03132         str = rb_str_dup(str);
03133     }
03134     OBJ_TAINT(str);  /* for safe */
03135     return str;
03136 }
03137 
03138 /*
03139  * Document-method: Zlib::GzipFile#comment
03140  *
03141  * Returns comments recorded in the gzip file header, or nil if the comments
03142  * is not present.
03143  */
03144 static VALUE
03145 rb_gzfile_comment(VALUE obj)
03146 {
03147     VALUE str = get_gzfile(obj)->comment;
03148     if (!NIL_P(str)) {
03149         str = rb_str_dup(str);
03150     }
03151     OBJ_TAINT(str);  /* for safe */
03152     return str;
03153 }
03154 
03155 /*
03156  * Document-method: Zlib::GzipFile#lineno
03157  *
03158  * The line number of the last row read from this file.
03159  */
03160 static VALUE
03161 rb_gzfile_lineno(VALUE obj)
03162 {
03163     return INT2NUM(get_gzfile(obj)->lineno);
03164 }
03165 
03166 /*
03167  * Document-method: Zlib::GzipReader#lineno=
03168  *
03169  * Specify line number of the last row read from this file.
03170  */
03171 static VALUE
03172 rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
03173 {
03174     struct gzfile *gz = get_gzfile(obj);
03175     gz->lineno = NUM2INT(lineno);
03176     return lineno;
03177 }
03178 
03179 /*
03180  * Document-method: Zlib::GzipWriter#mtime=
03181  *
03182  * Specify the modification time (+mtime+) in the gzip header.
03183  * Using a Fixnum or Integer
03184  */
03185 static VALUE
03186 rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
03187 {
03188     struct gzfile *gz = get_gzfile(obj);
03189     VALUE val;
03190 
03191     if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
03192         rb_raise(cGzError, "header is already written");
03193     }
03194 
03195     if (FIXNUM_P(mtime)) {
03196         gz->mtime = FIX2INT(mtime);
03197     }
03198     else {
03199         val = rb_Integer(mtime);
03200         gz->mtime = FIXNUM_P(val) ? FIX2UINT(val) : rb_big2ulong(val);
03201     }
03202     return mtime;
03203 }
03204 
03205 /*
03206  * Document-method: Zlib::GzipFile#orig_name=
03207  *
03208  * Specify the original name (+str+) in the gzip header.
03209  */
03210 static VALUE
03211 rb_gzfile_set_orig_name(VALUE obj, VALUE str)
03212 {
03213     struct gzfile *gz = get_gzfile(obj);
03214     VALUE s;
03215     char *p;
03216 
03217     if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
03218         rb_raise(cGzError, "header is already written");
03219     }
03220     s = rb_str_dup(rb_str_to_str(str));
03221     p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
03222     if (p) {
03223         rb_str_resize(s, p - RSTRING_PTR(s));
03224     }
03225     gz->orig_name = s;
03226     return str;
03227 }
03228 
03229 /*
03230  * Document-method: Zlib::GzipFile#comment=
03231  *
03232  * Specify the comment (+str+) in the gzip header.
03233  */
03234 static VALUE
03235 rb_gzfile_set_comment(VALUE obj, VALUE str)
03236 {
03237     struct gzfile *gz = get_gzfile(obj);
03238     VALUE s;
03239     char *p;
03240 
03241     if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
03242         rb_raise(cGzError, "header is already written");
03243     }
03244     s = rb_str_dup(rb_str_to_str(str));
03245     p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
03246     if (p) {
03247         rb_str_resize(s, p - RSTRING_PTR(s));
03248     }
03249     gz->comment = s;
03250     return str;
03251 }
03252 
03253 /*
03254  * Document-method: Zlib::GzipFile#close
03255  *
03256  * Closes the GzipFile object. This method calls close method of the
03257  * associated IO object. Returns the associated IO object.
03258  */
03259 static VALUE
03260 rb_gzfile_close(VALUE obj)
03261 {
03262     struct gzfile *gz = get_gzfile(obj);
03263     VALUE io;
03264 
03265     io = gz->io;
03266     gzfile_close(gz, 1);
03267     return io;
03268 }
03269 
03270 /*
03271  * Document-method: Zlib::GzipFile#finish
03272  *
03273  * Closes the GzipFile object. Unlike Zlib::GzipFile#close, this method never
03274  * calls the close method of the associated IO object. Returns the associated IO
03275  * object.
03276  */
03277 static VALUE
03278 rb_gzfile_finish(VALUE obj)
03279 {
03280     struct gzfile *gz = get_gzfile(obj);
03281     VALUE io;
03282 
03283     io = gz->io;
03284     gzfile_close(gz, 0);
03285     return io;
03286 }
03287 
03288 /*
03289  * Document-method: Zlib::GzipFile#closed?
03290  *
03291  * Same as IO#closed?
03292  *
03293  */
03294 static VALUE
03295 rb_gzfile_closed_p(VALUE obj)
03296 {
03297     struct gzfile *gz;
03298     Data_Get_Struct(obj, struct gzfile, gz);
03299     return NIL_P(gz->io) ? Qtrue : Qfalse;
03300 }
03301 
03302 /*
03303  * Document-method: Zlib::GzipFile#eof?
03304  *
03305  * Returns +true+ or +false+ whether the stream has reached the end.
03306  */
03307 static VALUE
03308 rb_gzfile_eof_p(VALUE obj)
03309 {
03310     struct gzfile *gz = get_gzfile(obj);
03311     return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
03312 }
03313 
03314 /*
03315  * Document-method: Zlib::GzipFile#sync
03316  *
03317  * Same as IO#sync
03318  *
03319  */
03320 static VALUE
03321 rb_gzfile_sync(VALUE obj)
03322 {
03323     return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
03324 }
03325 
03326 /*
03327  * Document-method: Zlib::GzipFile#sync=
03328  *
03329  * call-seq: sync = flag
03330  *
03331  * Same as IO.  If flag is +true+, the associated IO object must respond to the
03332  * +flush+ method.  While +sync+ mode is +true+, the compression ratio
03333  * decreases sharply.
03334  */
03335 static VALUE
03336 rb_gzfile_set_sync(VALUE obj, VALUE mode)
03337 {
03338     struct gzfile *gz = get_gzfile(obj);
03339 
03340     if (RTEST(mode)) {
03341         gz->z.flags |= GZFILE_FLAG_SYNC;
03342     }
03343     else {
03344         gz->z.flags &= ~GZFILE_FLAG_SYNC;
03345     }
03346     return mode;
03347 }
03348 
03349 /*
03350  * Document-method: Zlib::GzipFile#total_in
03351  *
03352  * Total number of input bytes read so far.
03353  */
03354 static VALUE
03355 rb_gzfile_total_in(VALUE obj)
03356 {
03357     return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
03358 }
03359 
03360 /*
03361  * Document-method: Zlib::GzipFile#total_out
03362  *
03363  * Total number of output bytes output so far.
03364  */
03365 static VALUE
03366 rb_gzfile_total_out(VALUE obj)
03367 {
03368     struct gzfile *gz = get_gzfile(obj);
03369     return rb_uint2inum(gz->z.stream.total_out - gz->z.buf_filled);
03370 }
03371 
03372 /*
03373  * Document-method: Zlib::GzipFile#path
03374  *
03375  * call-seq: path
03376  *
03377  * Returns the path string of the associated IO-like object.  This
03378  * method is only defined when the IO-like object responds to #path().
03379  */
03380 static VALUE
03381 rb_gzfile_path(VALUE obj)
03382 {
03383     struct gzfile *gz;
03384     Data_Get_Struct(obj, struct gzfile, gz);
03385     return gz->path;
03386 }
03387 
03388 static void
03389 rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
03390 {
03391     if (!NIL_P(opts)) {
03392         rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2, NULL);
03393     }
03394     if (gz->enc2) {
03395         gz->ecflags = rb_econv_prepare_opts(opts, &opts);
03396         gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
03397                                     gz->ecflags, opts);
03398         gz->ecopts = opts;
03399     }
03400 }
03401 
03402 /* ------------------------------------------------------------------------- */
03403 
03404 /*
03405  * Document-class: Zlib::GzipWriter
03406  *
03407  * Zlib::GzipWriter is a class for writing gzipped files.  GzipWriter should
03408  * be used with an instance of IO, or IO-like, object.
03409  *
03410  * Following two example generate the same result.
03411  *
03412  *   Zlib::GzipWriter.open('hoge.gz') do |gz|
03413  *     gz.write 'jugemu jugemu gokou no surikire...'
03414  *   end
03415  *
03416  *   File.open('hoge.gz', 'w') do |f|
03417  *     gz = Zlib::GzipWriter.new(f)
03418  *     gz.write 'jugemu jugemu gokou no surikire...'
03419  *     gz.close
03420  *   end
03421  *
03422  * To make like gzip(1) does, run following:
03423  *
03424  *   orig = 'hoge.txt'
03425  *   Zlib::GzipWriter.open('hoge.gz') do |gz|
03426  *     gz.mtime = File.mtime(orig)
03427  *     gz.orig_name = orig
03428  *     gz.write IO.binread(orig)
03429  *   end
03430  *
03431  * NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close
03432  * GzipWriter objects by Zlib::GzipWriter#close etc.  Otherwise, GzipWriter
03433  * will be not able to write the gzip footer and will generate a broken gzip
03434  * file.
03435  */
03436 
03437 static VALUE
03438 rb_gzwriter_s_allocate(VALUE klass)
03439 {
03440     return gzfile_writer_new(klass);
03441 }
03442 
03443 /*
03444  * call-seq: Zlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... }
03445  *
03446  * Opens a file specified by +filename+ for writing gzip compressed data, and
03447  * returns a GzipWriter object associated with that file.  Further details of
03448  * this method are found in Zlib::GzipWriter.new and Zlib::GzipFile.wrap.
03449  */
03450 static VALUE
03451 rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
03452 {
03453     return gzfile_s_open(argc, argv, klass, "wb");
03454 }
03455 
03456 /*
03457  * call-seq:
03458  *   Zlib::GzipWriter.new(io, level = nil, strategy = nil, options = {})
03459  *
03460  * Creates a GzipWriter object associated with +io+. +level+ and +strategy+
03461  * should be the same as the arguments of Zlib::Deflate.new.  The GzipWriter
03462  * object writes gzipped data to +io+.  +io+ must respond to the
03463  * +write+ method that behaves the same as IO#write.
03464  *
03465  * The +options+ hash may be used to set the encoding of the data.
03466  * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
03467  * IO::new.
03468  */
03469 static VALUE
03470 rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
03471 {
03472     struct gzfile *gz;
03473     VALUE io, level, strategy, opt = Qnil;
03474     int err;
03475 
03476     if (argc > 1) {
03477         opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
03478         if (!NIL_P(opt)) argc--;
03479     }
03480 
03481     rb_scan_args(argc, argv, "12", &io, &level, &strategy);
03482     Data_Get_Struct(obj, struct gzfile, gz);
03483 
03484     /* this is undocumented feature of zlib */
03485     gz->level = ARG_LEVEL(level);
03486     err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
03487                        -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
03488     if (err != Z_OK) {
03489         raise_zlib_error(err, gz->z.stream.msg);
03490     }
03491     gz->io = io;
03492     ZSTREAM_READY(&gz->z);
03493     rb_gzfile_ecopts(gz, opt);
03494 
03495     if (rb_respond_to(io, id_path)) {
03496         gz->path = rb_funcall(gz->io, id_path, 0);
03497         rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
03498     }
03499 
03500     return obj;
03501 }
03502 
03503 /*
03504  * call-seq: flush(flush=nil)
03505  *
03506  * Flushes all the internal buffers of the GzipWriter object.  The meaning of
03507  * +flush+ is same as in Zlib::Deflate#deflate.  <tt>Zlib::SYNC_FLUSH</tt> is used if
03508  * +flush+ is omitted.  It is no use giving flush <tt>Zlib::NO_FLUSH</tt>.
03509  */
03510 static VALUE
03511 rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
03512 {
03513     struct gzfile *gz = get_gzfile(obj);
03514     VALUE v_flush;
03515     int flush;
03516 
03517     rb_scan_args(argc, argv, "01", &v_flush);
03518 
03519     flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
03520     if (flush != Z_NO_FLUSH) {  /* prevent Z_BUF_ERROR */
03521         zstream_run(&gz->z, (Bytef*)"", 0, flush);
03522     }
03523 
03524     gzfile_write_raw(gz);
03525     if (rb_respond_to(gz->io, id_flush)) {
03526         rb_funcall(gz->io, id_flush, 0);
03527     }
03528     return obj;
03529 }
03530 
03531 /*
03532  * Same as IO.
03533  */
03534 static VALUE
03535 rb_gzwriter_write(VALUE obj, VALUE str)
03536 {
03537     struct gzfile *gz = get_gzfile(obj);
03538 
03539     if (!RB_TYPE_P(str, T_STRING))
03540         str = rb_obj_as_string(str);
03541     if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
03542         str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
03543     }
03544     gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
03545     return INT2FIX(RSTRING_LEN(str));
03546 }
03547 
03548 /*
03549  * Same as IO.
03550  */
03551 static VALUE
03552 rb_gzwriter_putc(VALUE obj, VALUE ch)
03553 {
03554     struct gzfile *gz = get_gzfile(obj);
03555     char c = NUM2CHR(ch);
03556 
03557     gzfile_write(gz, (Bytef*)&c, 1);
03558     return ch;
03559 }
03560 
03561 
03562 
03563 /*
03564  * Document-method: <<
03565  * Same as IO.
03566  */
03567 #define rb_gzwriter_addstr  rb_io_addstr
03568 /*
03569  * Document-method: printf
03570  * Same as IO.
03571  */
03572 #define rb_gzwriter_printf  rb_io_printf
03573 /*
03574  * Document-method: print
03575  * Same as IO.
03576  */
03577 #define rb_gzwriter_print  rb_io_print
03578 /*
03579  * Document-method: puts
03580  * Same as IO.
03581  */
03582 #define rb_gzwriter_puts  rb_io_puts
03583 
03584 
03585 /* ------------------------------------------------------------------------- */
03586 
03587 /*
03588  * Document-class: Zlib::GzipReader
03589  *
03590  * Zlib::GzipReader is the class for reading a gzipped file.  GzipReader should
03591  * be used an IO, or -IO-like, object.
03592  *
03593  *   Zlib::GzipReader.open('hoge.gz') {|gz|
03594  *     print gz.read
03595  *   }
03596  *
03597  *   File.open('hoge.gz') do |f|
03598  *     gz = Zlib::GzipReader.new(f)
03599  *     print gz.read
03600  *     gz.close
03601  *   end
03602  *
03603  * == Method Catalogue
03604  *
03605  * The following methods in Zlib::GzipReader are just like their counterparts
03606  * in IO, but they raise Zlib::Error or Zlib::GzipFile::Error exception if an
03607  * error was found in the gzip file.
03608  * - #each
03609  * - #each_line
03610  * - #each_byte
03611  * - #gets
03612  * - #getc
03613  * - #lineno
03614  * - #lineno=
03615  * - #read
03616  * - #readchar
03617  * - #readline
03618  * - #readlines
03619  * - #ungetc
03620  *
03621  * Be careful of the footer of the gzip file. A gzip file has the checksum of
03622  * pre-compressed data in its footer. GzipReader checks all uncompressed data
03623  * against that checksum at the following cases, and if it fails, raises
03624  * <tt>Zlib::GzipFile::NoFooter</tt>, <tt>Zlib::GzipFile::CRCError</tt>, or
03625  * <tt>Zlib::GzipFile::LengthError</tt> exception.
03626  *
03627  * - When an reading request is received beyond the end of file (the end of
03628  *   compressed data). That is, when Zlib::GzipReader#read,
03629  *   Zlib::GzipReader#gets, or some other methods for reading returns nil.
03630  * - When Zlib::GzipFile#close method is called after the object reaches the
03631  *   end of file.
03632  * - When Zlib::GzipReader#unused method is called after the object reaches
03633  *   the end of file.
03634  *
03635  * The rest of the methods are adequately described in their own
03636  * documentation.
03637  */
03638 
03639 static VALUE
03640 rb_gzreader_s_allocate(VALUE klass)
03641 {
03642     return gzfile_reader_new(klass);
03643 }
03644 
03645 /*
03646  * Document-method: Zlib::GzipReader.open
03647  *
03648  * call-seq: Zlib::GzipReader.open(filename) {|gz| ... }
03649  *
03650  * Opens a file specified by +filename+ as a gzipped file, and returns a
03651  * GzipReader object associated with that file.  Further details of this method
03652  * are in Zlib::GzipReader.new and ZLib::GzipFile.wrap.
03653  */
03654 static VALUE
03655 rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
03656 {
03657     return gzfile_s_open(argc, argv, klass, "rb");
03658 }
03659 
03660 /*
03661  * Document-method: Zlib::GzipReader.new
03662  *
03663  * call-seq:
03664  *   Zlib::GzipReader.new(io, options = {})
03665  *
03666  * Creates a GzipReader object associated with +io+. The GzipReader object reads
03667  * gzipped data from +io+, and parses/decompresses it.  The +io+ must
03668  * have a +read+ method that behaves same as the IO#read.
03669  *
03670  * The +options+ hash may be used to set the encoding of the data.
03671  * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
03672  * IO::new.
03673  *
03674  * If the gzip file header is incorrect, raises an Zlib::GzipFile::Error
03675  * exception.
03676  */
03677 static VALUE
03678 rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
03679 {
03680     VALUE io, opt = Qnil;
03681     struct gzfile *gz;
03682     int err;
03683 
03684     Data_Get_Struct(obj, struct gzfile, gz);
03685     rb_scan_args(argc, argv, "1:", &io, &opt);
03686 
03687     /* this is undocumented feature of zlib */
03688     err = inflateInit2(&gz->z.stream, -MAX_WBITS);
03689     if (err != Z_OK) {
03690         raise_zlib_error(err, gz->z.stream.msg);
03691     }
03692     gz->io = io;
03693     ZSTREAM_READY(&gz->z);
03694     gzfile_read_header(gz);
03695     rb_gzfile_ecopts(gz, opt);
03696 
03697     if (rb_respond_to(io, id_path)) {
03698         gz->path = rb_funcall(gz->io, id_path, 0);
03699         rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
03700     }
03701 
03702     return obj;
03703 }
03704 
03705 /*
03706  * Document-method: Zlib::GzipReader#rewind
03707  *
03708  * Resets the position of the file pointer to the point created the GzipReader
03709  * object.  The associated IO object needs to respond to the +seek+ method.
03710  */
03711 static VALUE
03712 rb_gzreader_rewind(VALUE obj)
03713 {
03714     struct gzfile *gz = get_gzfile(obj);
03715     gzfile_reader_rewind(gz);
03716     return INT2FIX(0);
03717 }
03718 
03719 /*
03720  * Document-method: Zlib::GzipReader#unused
03721  *
03722  * Returns the rest of the data which had read for parsing gzip format, or
03723  * +nil+ if the whole gzip file is not parsed yet.
03724  */
03725 static VALUE
03726 rb_gzreader_unused(VALUE obj)
03727 {
03728     struct gzfile *gz;
03729     Data_Get_Struct(obj, struct gzfile, gz);
03730     return gzfile_reader_get_unused(gz);
03731 }
03732 
03733 /*
03734  * Document-method: Zlib::GzipReader#read
03735  *
03736  * See Zlib::GzipReader documentation for a description.
03737  */
03738 static VALUE
03739 rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
03740 {
03741     struct gzfile *gz = get_gzfile(obj);
03742     VALUE vlen;
03743     long len;
03744 
03745     rb_scan_args(argc, argv, "01", &vlen);
03746     if (NIL_P(vlen)) {
03747         return gzfile_read_all(gz);
03748     }
03749 
03750     len = NUM2INT(vlen);
03751     if (len < 0) {
03752         rb_raise(rb_eArgError, "negative length %ld given", len);
03753     }
03754     return gzfile_read(gz, len);
03755 }
03756 
03757 /*
03758  * Document-method: Zlib::GzipReader#readpartial
03759  *
03760  *  call-seq:
03761  *     gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
03762  *
03763  *  Reads at most <i>maxlen</i> bytes from the gziped stream but
03764  *  it blocks only if <em>gzipreader</em> has no data immediately available.
03765  *  If the optional <i>outbuf</i> argument is present,
03766  *  it must reference a String, which will receive the data.
03767  *  It raises <code>EOFError</code> on end of file.
03768  */
03769 static VALUE
03770 rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
03771 {
03772     struct gzfile *gz = get_gzfile(obj);
03773     VALUE vlen, outbuf;
03774     long len;
03775 
03776     rb_scan_args(argc, argv, "11", &vlen, &outbuf);
03777 
03778     len = NUM2INT(vlen);
03779     if (len < 0) {
03780         rb_raise(rb_eArgError, "negative length %ld given", len);
03781     }
03782     if (!NIL_P(outbuf))
03783         Check_Type(outbuf, T_STRING);
03784     return gzfile_readpartial(gz, len, outbuf);
03785 }
03786 
03787 /*
03788  * Document-method: Zlib::GzipReader#getc
03789  *
03790  * See Zlib::GzipReader documentation for a description.
03791  */
03792 static VALUE
03793 rb_gzreader_getc(VALUE obj)
03794 {
03795     struct gzfile *gz = get_gzfile(obj);
03796 
03797     return gzfile_getc(gz);
03798 }
03799 
03800 /*
03801  * Document-method: Zlib::GzipReader#readchar
03802  *
03803  * See Zlib::GzipReader documentation for a description.
03804  */
03805 static VALUE
03806 rb_gzreader_readchar(VALUE obj)
03807 {
03808     VALUE dst;
03809     dst = rb_gzreader_getc(obj);
03810     if (NIL_P(dst)) {
03811         rb_raise(rb_eEOFError, "end of file reached");
03812     }
03813     return dst;
03814 }
03815 
03816 /*
03817  * Document-method: Zlib::GzipReader#getbyte
03818  *
03819  * See Zlib::GzipReader documentation for a description.
03820  */
03821 static VALUE
03822 rb_gzreader_getbyte(VALUE obj)
03823 {
03824     struct gzfile *gz = get_gzfile(obj);
03825     VALUE dst;
03826 
03827     dst = gzfile_read(gz, 1);
03828     if (!NIL_P(dst)) {
03829         dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
03830     }
03831     return dst;
03832 }
03833 
03834 /*
03835  * Document-method: Zlib::GzipReader#readbyte
03836  *
03837  * See Zlib::GzipReader documentation for a description.
03838  */
03839 static VALUE
03840 rb_gzreader_readbyte(VALUE obj)
03841 {
03842     VALUE dst;
03843     dst = rb_gzreader_getbyte(obj);
03844     if (NIL_P(dst)) {
03845         rb_raise(rb_eEOFError, "end of file reached");
03846     }
03847     return dst;
03848 }
03849 
03850 /*
03851  * Document-method: Zlib::GzipReader#each_char
03852  *
03853  * See Zlib::GzipReader documentation for a description.
03854  */
03855 static VALUE
03856 rb_gzreader_each_char(VALUE obj)
03857 {
03858     VALUE c;
03859 
03860     RETURN_ENUMERATOR(obj, 0, 0);
03861 
03862     while (!NIL_P(c = rb_gzreader_getc(obj))) {
03863         rb_yield(c);
03864     }
03865     return Qnil;
03866 }
03867 
03868 /*
03869  * Document-method: Zlib::GzipReader#each_byte
03870  *
03871  * See Zlib::GzipReader documentation for a description.
03872  */
03873 static VALUE
03874 rb_gzreader_each_byte(VALUE obj)
03875 {
03876     VALUE c;
03877 
03878     RETURN_ENUMERATOR(obj, 0, 0);
03879 
03880     while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
03881         rb_yield(c);
03882     }
03883     return Qnil;
03884 }
03885 
03886 /*
03887  * Document-method: Zlib::GzipReader#bytes
03888  *
03889  *  This is a deprecated alias for <code>each_byte</code>.
03890  */
03891 static VALUE
03892 rb_gzreader_bytes(VALUE obj)
03893 {
03894     rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
03895     if (!rb_block_given_p())
03896         return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
03897     return rb_gzreader_each_byte(obj);
03898 }
03899 
03900 /*
03901  * Document-method: Zlib::GzipReader#ungetc
03902  *
03903  * See Zlib::GzipReader documentation for a description.
03904  */
03905 static VALUE
03906 rb_gzreader_ungetc(VALUE obj, VALUE s)
03907 {
03908     struct gzfile *gz;
03909 
03910     if (FIXNUM_P(s))
03911         return rb_gzreader_ungetbyte(obj, s);
03912     gz = get_gzfile(obj);
03913     StringValue(s);
03914     if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
03915         s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
03916     }
03917     gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
03918     return Qnil;
03919 }
03920 
03921 /*
03922  * Document-method: Zlib::GzipReader#ungetbyte
03923  *
03924  * See Zlib::GzipReader documentation for a description.
03925  */
03926 static VALUE
03927 rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
03928 {
03929     struct gzfile *gz = get_gzfile(obj);
03930     gzfile_ungetbyte(gz, NUM2CHR(ch));
03931     return Qnil;
03932 }
03933 
03934 static void
03935 gzreader_skip_linebreaks(struct gzfile *gz)
03936 {
03937     VALUE str;
03938     char *p;
03939     int n;
03940 
03941     while (gz->z.buf_filled == 0) {
03942         if (GZFILE_IS_FINISHED(gz)) return;
03943         gzfile_read_more(gz);
03944     }
03945     n = 0;
03946     p = RSTRING_PTR(gz->z.buf);
03947 
03948     while (n++, *(p++) == '\n') {
03949         if (n >= gz->z.buf_filled) {
03950             str = zstream_detach_buffer(&gz->z);
03951             gzfile_calc_crc(gz, str);
03952             while (gz->z.buf_filled == 0) {
03953                 if (GZFILE_IS_FINISHED(gz)) return;
03954                 gzfile_read_more(gz);
03955             }
03956             n = 0;
03957             p = RSTRING_PTR(gz->z.buf);
03958         }
03959     }
03960 
03961     str = zstream_shift_buffer(&gz->z, n - 1);
03962     gzfile_calc_crc(gz, str);
03963 }
03964 
03965 static void
03966 rscheck(const char *rsptr, long rslen, VALUE rs)
03967 {
03968     if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
03969         rb_raise(rb_eRuntimeError, "rs modified");
03970 }
03971 
03972 static long
03973 gzreader_charboundary(struct gzfile *gz, long n)
03974 {
03975     char *s = RSTRING_PTR(gz->z.buf);
03976     char *e = s + gz->z.buf_filled;
03977     char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
03978     long l = p - s;
03979     if (l < n) {
03980         n = rb_enc_precise_mbclen(p, e, gz->enc);
03981         if (MBCLEN_NEEDMORE_P(n)) {
03982             if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
03983                 return l;
03984             }
03985         }
03986         else if (MBCLEN_CHARFOUND_P(n)) {
03987             return l + MBCLEN_CHARFOUND_LEN(n);
03988         }
03989     }
03990     return n;
03991 }
03992 
03993 static VALUE
03994 gzreader_gets(int argc, VALUE *argv, VALUE obj)
03995 {
03996     struct gzfile *gz = get_gzfile(obj);
03997     volatile VALUE rs;
03998     VALUE dst;
03999     const char *rsptr;
04000     char *p, *res;
04001     long rslen, n, limit = -1;
04002     int rspara;
04003     rb_encoding *enc = gz->enc;
04004     int maxlen = rb_enc_mbmaxlen(enc);
04005 
04006     if (argc == 0) {
04007         rs = rb_rs;
04008     }
04009     else {
04010         VALUE lim, tmp;
04011 
04012         rb_scan_args(argc, argv, "11", &rs, &lim);
04013         if (!NIL_P(lim)) {
04014             if (!NIL_P(rs)) StringValue(rs);
04015         }
04016         else if (!NIL_P(rs)) {
04017             tmp = rb_check_string_type(rs);
04018             if (NIL_P(tmp)) {
04019                 lim = rs;
04020                 rs = rb_rs;
04021             }
04022             else {
04023                 rs = tmp;
04024             }
04025         }
04026         if (!NIL_P(lim)) {
04027             limit = NUM2LONG(lim);
04028             if (limit == 0) return rb_str_new(0,0);
04029         }
04030     }
04031 
04032     if (NIL_P(rs)) {
04033         if (limit < 0) {
04034             dst = gzfile_read_all(gz);
04035             if (RSTRING_LEN(dst) == 0) return Qnil;
04036         }
04037         else if ((n = gzfile_fill(gz, limit)) <= 0) {
04038             return Qnil;
04039         }
04040         else {
04041             if (maxlen > 1 && n >= limit && !GZFILE_IS_FINISHED(gz)) {
04042                 n = gzreader_charboundary(gz, n);
04043             }
04044             else {
04045                 n = limit;
04046             }
04047             dst = zstream_shift_buffer(&gz->z, n);
04048             if (NIL_P(dst)) return dst;
04049             gzfile_calc_crc(gz, dst);
04050             dst = gzfile_newstr(gz, dst);
04051         }
04052         gz->lineno++;
04053         return dst;
04054     }
04055 
04056     if (RSTRING_LEN(rs) == 0) {
04057         rsptr = "\n\n";
04058         rslen = 2;
04059         rspara = 1;
04060     } else {
04061         rsptr = RSTRING_PTR(rs);
04062         rslen = RSTRING_LEN(rs);
04063         rspara = 0;
04064     }
04065 
04066     if (rspara) {
04067         gzreader_skip_linebreaks(gz);
04068     }
04069 
04070     while (gz->z.buf_filled < rslen) {
04071         if (ZSTREAM_IS_FINISHED(&gz->z)) {
04072             if (gz->z.buf_filled > 0) gz->lineno++;
04073             return gzfile_read(gz, rslen);
04074         }
04075         gzfile_read_more(gz);
04076     }
04077 
04078     p = RSTRING_PTR(gz->z.buf);
04079     n = rslen;
04080     for (;;) {
04081         long filled;
04082         if (n > gz->z.buf_filled) {
04083             if (ZSTREAM_IS_FINISHED(&gz->z)) break;
04084             gzfile_read_more(gz);
04085             p = RSTRING_PTR(gz->z.buf) + n - rslen;
04086         }
04087         if (!rspara) rscheck(rsptr, rslen, rs);
04088         filled = gz->z.buf_filled;
04089         if (limit > 0 && filled >= limit) {
04090             filled = limit;
04091         }
04092         res = memchr(p, rsptr[0], (filled - n + 1));
04093         if (!res) {
04094             n = filled;
04095             if (limit > 0 && filled >= limit) break;
04096             n++;
04097         } else {
04098             n += (long)(res - p);
04099             p = res;
04100             if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
04101             p++, n++;
04102         }
04103     }
04104     if (maxlen > 1 && n == limit && (gz->z.buf_filled > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
04105         n = gzreader_charboundary(gz, n);
04106     }
04107 
04108     gz->lineno++;
04109     dst = gzfile_read(gz, n);
04110     if (NIL_P(dst)) return dst;
04111     if (rspara) {
04112         gzreader_skip_linebreaks(gz);
04113     }
04114 
04115     return gzfile_newstr(gz, dst);
04116 }
04117 
04118 /*
04119  * Document-method: Zlib::GzipReader#gets
04120  *
04121  * See Zlib::GzipReader documentation for a description.
04122  */
04123 static VALUE
04124 rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
04125 {
04126     VALUE dst;
04127     dst = gzreader_gets(argc, argv, obj);
04128     if (!NIL_P(dst)) {
04129         rb_lastline_set(dst);
04130     }
04131     return dst;
04132 }
04133 
04134 /*
04135  * Document-method: Zlib::GzipReader#readline
04136  *
04137  * See Zlib::GzipReader documentation for a description.
04138  */
04139 static VALUE
04140 rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
04141 {
04142     VALUE dst;
04143     dst = rb_gzreader_gets(argc, argv, obj);
04144     if (NIL_P(dst)) {
04145         rb_raise(rb_eEOFError, "end of file reached");
04146     }
04147     return dst;
04148 }
04149 
04150 /*
04151  * Document-method: Zlib::GzipReader#each
04152  *
04153  * See Zlib::GzipReader documentation for a description.
04154  */
04155 static VALUE
04156 rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
04157 {
04158     VALUE str;
04159 
04160     RETURN_ENUMERATOR(obj, 0, 0);
04161 
04162     while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
04163         rb_yield(str);
04164     }
04165     return obj;
04166 }
04167 
04168 /*
04169  * Document-method: Zlib::GzipReader#lines
04170  *
04171  *  This is a deprecated alias for <code>each_line</code>.
04172  */
04173 static VALUE
04174 rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
04175 {
04176     rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
04177     if (!rb_block_given_p())
04178         return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
04179     return rb_gzreader_each(argc, argv, obj);
04180 }
04181 
04182 /*
04183  * Document-method: Zlib::GzipReader#readlines
04184  *
04185  * See Zlib::GzipReader documentation for a description.
04186  */
04187 static VALUE
04188 rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
04189 {
04190     VALUE str, dst;
04191     dst = rb_ary_new();
04192     while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
04193         rb_ary_push(dst, str);
04194     }
04195     return dst;
04196 }
04197 
04198 #endif /* GZIP_SUPPORT */
04199 
04200 void
04201 Init_zlib()
04202 {
04203     VALUE mZlib, cZStream, cDeflate, cInflate;
04204 #if GZIP_SUPPORT
04205     VALUE cGzipFile, cGzipWriter, cGzipReader;
04206 #endif
04207 
04208     mZlib = rb_define_module("Zlib");
04209 
04210     id_dictionaries = rb_intern("@dictionaries");
04211 
04212     cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
04213     cStreamEnd    = rb_define_class_under(mZlib, "StreamEnd", cZError);
04214     cNeedDict     = rb_define_class_under(mZlib, "NeedDict", cZError);
04215     cDataError    = rb_define_class_under(mZlib, "DataError", cZError);
04216     cStreamError  = rb_define_class_under(mZlib, "StreamError", cZError);
04217     cMemError     = rb_define_class_under(mZlib, "MemError", cZError);
04218     cBufError     = rb_define_class_under(mZlib, "BufError", cZError);
04219     cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
04220 
04221     rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
04222     rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
04223     rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
04224     rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
04225     rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
04226     rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
04227 
04228     /* The Ruby/zlib version string. */
04229     rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
04230     /*  The string which represents the version of zlib.h */
04231     rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
04232 
04233     cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
04234     rb_undef_alloc_func(cZStream);
04235     rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
04236     rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
04237     rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
04238     rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
04239     rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
04240     rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
04241     rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
04242     rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
04243     rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
04244     rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
04245     rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
04246     rb_define_method(cZStream, "close", rb_zstream_end, 0);
04247     rb_define_method(cZStream, "end", rb_zstream_end, 0);
04248     rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
04249     rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
04250     rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
04251     rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
04252 
04253     /* Represents binary data as guessed by deflate.
04254      *
04255      * See Zlib::Deflate#data_type. */
04256     rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
04257 
04258     /* Represents text data as guessed by deflate.
04259      *
04260      * NOTE: The underlying constant Z_ASCII was deprecated in favor of Z_TEXT
04261      * in zlib 1.2.2.  New applications should not use this constant.
04262      *
04263      * See Zlib::Deflate#data_type. */
04264     rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
04265 
04266 #ifdef Z_TEXT
04267     /* Represents text data as guessed by deflate.
04268      *
04269      * See Zlib::Deflate#data_type. */
04270     rb_define_const(mZlib, "TEXT", INT2FIX(Z_TEXT));
04271 #endif
04272 
04273     /* Represents an unknown data type as guessed by deflate.
04274      *
04275      * See Zlib::Deflate#data_type. */
04276     rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
04277 
04278     cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
04279     rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
04280     rb_define_singleton_method(mZlib, "deflate", rb_deflate_s_deflate, -1);
04281     rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
04282     rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
04283     rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
04284     rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
04285     rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
04286     rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
04287     rb_define_method(cDeflate, "params", rb_deflate_params, 2);
04288     rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
04289 
04290     cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
04291     rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
04292     rb_define_singleton_method(mZlib, "inflate", rb_inflate_s_inflate, 1);
04293     rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
04294     rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
04295     rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
04296     rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
04297     rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
04298     rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
04299     rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
04300     rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
04301 
04302     /* No compression, passes through data untouched.  Use this for appending
04303      * pre-compressed data to a deflate stream.
04304      */
04305     rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
04306     /* Fastest compression level, but with with lowest space savings. */
04307     rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
04308     /* Slowest compression level, but with the best space savings. */
04309     rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
04310     /* Default compression level which is a good trade-off between space and
04311      * time
04312      */
04313     rb_define_const(mZlib, "DEFAULT_COMPRESSION",
04314                     INT2FIX(Z_DEFAULT_COMPRESSION));
04315 
04316     /* Deflate strategy for data produced by a filter (or predictor). The
04317      * effect of FILTERED is to force more Huffman codes and less string
04318      * matching; it is somewhat intermediate between DEFAULT_STRATEGY and
04319      * HUFFMAN_ONLY. Filtered data consists mostly of small values with a
04320      * somewhat random distribution.
04321      */
04322     rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
04323 
04324     /* Deflate strategy which uses Huffman codes only (no string matching). */
04325     rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
04326 
04327 #ifdef Z_RLE
04328     /* Deflate compression strategy designed to be almost as fast as
04329      * HUFFMAN_ONLY, but give better compression for PNG image data.
04330      */
04331     rb_define_const(mZlib, "RLE", INT2FIX(Z_RLE));
04332 #endif
04333 
04334 #ifdef Z_FIXED
04335     /* Deflate strategy which prevents the use of dynamic Huffman codes,
04336      * allowing for a simpler decoder for specialized applications.
04337      */
04338     rb_define_const(mZlib, "FIXED", INT2FIX(Z_FIXED));
04339 #endif
04340 
04341     /* Default deflate strategy which is used for normal data. */
04342     rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
04343 
04344     /* The maximum size of the zlib history buffer.  Note that zlib allows
04345      * larger values to enable different inflate modes.  See Zlib::Inflate.new
04346      * for details.
04347      */
04348     rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
04349 
04350     /* The default memory level for allocating zlib deflate compression state.
04351      */
04352     rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
04353 
04354     /* The maximum memory level for allocating zlib deflate compression state.
04355      */
04356     rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
04357 
04358     /* NO_FLUSH is the default flush method and allows deflate to decide how
04359      * much data to accumulate before producing output in order to maximize
04360      * compression.
04361      */
04362     rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
04363 
04364     /* The SYNC_FLUSH method flushes all pending output to the output buffer
04365      * and the output is aligned on a byte boundary. Flushing may degrade
04366      * compression so it should be used only when necessary, such as at a
04367      * request or response boundary for a network stream.
04368      */
04369     rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
04370 
04371     /* Flushes all output as with SYNC_FLUSH, and the compression state is
04372      * reset so that decompression can restart from this point if previous
04373      * compressed data has been damaged or if random access is desired. Like
04374      * SYNC_FLUSH, using FULL_FLUSH too often can seriously degrade
04375      * compression.
04376      */
04377     rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
04378 
04379     /* Processes all pending input and flushes pending output. */
04380     rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
04381 
04382 #if GZIP_SUPPORT
04383     id_write = rb_intern("write");
04384     id_read = rb_intern("read");
04385     id_readpartial = rb_intern("readpartial");
04386     id_flush = rb_intern("flush");
04387     id_seek = rb_intern("seek");
04388     id_close = rb_intern("close");
04389     id_path = rb_intern("path");
04390     id_input = rb_intern("@input");
04391 
04392     cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
04393     cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
04394 
04395     /* input gzipped string */
04396     rb_define_attr(cGzError, "input", 1, 0);
04397     rb_define_method(cGzError, "inspect", gzfile_error_inspect, 0);
04398 
04399     cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
04400     cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
04401     cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
04402 
04403     cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
04404     cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
04405     rb_include_module(cGzipReader, rb_mEnumerable);
04406 
04407     rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
04408     rb_undef_alloc_func(cGzipFile);
04409     rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
04410     rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
04411     rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
04412     rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
04413     rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
04414     rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
04415     rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
04416     rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
04417     rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
04418     rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
04419     rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
04420     rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
04421     rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
04422     rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
04423     rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
04424     rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
04425     rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
04426     rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
04427     rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
04428     rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
04429     rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
04430     rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
04431     rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
04432 
04433     rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
04434     rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
04435     rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
04436     rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
04437     rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
04438     rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
04439     rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
04440     rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
04441     rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
04442     rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
04443 
04444     rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
04445     rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
04446     rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
04447     rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
04448     rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
04449     rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
04450     rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
04451     rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
04452     rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
04453     rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
04454     rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
04455     rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
04456     rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
04457     rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
04458     rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
04459     rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
04460     rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
04461     rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
04462     rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
04463     rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
04464     rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
04465     rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
04466 
04467     /* The OS code of current host */
04468     rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
04469     /* OS code for MSDOS hosts */
04470     rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
04471     /* OS code for Amiga hosts */
04472     rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
04473     /* OS code for VMS hosts */
04474     rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
04475     /* OS code for UNIX hosts */
04476     rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
04477     /* OS code for Atari hosts */
04478     rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
04479     /* OS code for OS2 hosts */
04480     rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
04481     /* OS code for Mac OS hosts */
04482     rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
04483     /* OS code for TOPS-20 hosts */
04484     rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
04485     /* OS code for Win32 hosts */
04486     rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
04487     /* OS code for VM OS hosts */
04488     rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
04489     /* OS code for Z-System hosts */
04490     rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
04491     /* OS code for CP/M hosts */
04492     rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
04493     /* OS code for QDOS hosts */
04494     rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
04495     /* OS code for RISC OS hosts */
04496     rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
04497     /* OS code for unknown hosts */
04498     rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
04499 
04500 #endif /* GZIP_SUPPORT */
04501 }
04502 
04503 /* Document error classes. */
04504 
04505 /*
04506  * Document-class: Zlib::Error
04507  *
04508  * The superclass for all exceptions raised by Ruby/zlib.
04509  *
04510  * The following exceptions are defined as subclasses of Zlib::Error. These
04511  * exceptions are raised when zlib library functions return with an error
04512  * status.
04513  *
04514  * - Zlib::StreamEnd
04515  * - Zlib::NeedDict
04516  * - Zlib::DataError
04517  * - Zlib::StreamError
04518  * - Zlib::MemError
04519  * - Zlib::BufError
04520  * - Zlib::VersionError
04521  *
04522  */
04523 
04524 /*
04525  * Document-class: Zlib::StreamEnd
04526  *
04527  * Subclass of Zlib::Error
04528  *
04529  * When zlib returns a Z_STREAM_END
04530  * is return if the end of the compressed data has been reached
04531  * and all uncompressed out put has been produced.
04532  *
04533  */
04534 
04535 /*
04536  * Document-class: Zlib::NeedDict
04537  *
04538  * Subclass of Zlib::Error
04539  *
04540  * When zlib returns a Z_NEED_DICT
04541  * if a preset dictionary is needed at this point.
04542  *
04543  * Used by Zlib::Inflate.inflate and <tt>Zlib.inflate</tt>
04544  */
04545 
04546 /*
04547  * Document-class: Zlib::VersionError
04548  *
04549  * Subclass of Zlib::Error
04550  *
04551  * When zlib returns a Z_VERSION_ERROR,
04552  * usually if the zlib library version is incompatible with the
04553  * version assumed by the caller.
04554  *
04555  */
04556 
04557 /*
04558  * Document-class: Zlib::MemError
04559  *
04560  * Subclass of Zlib::Error
04561  *
04562  * When zlib returns a Z_MEM_ERROR,
04563  * usually if there was not enough memory.
04564  *
04565  */
04566 
04567 /*
04568  * Document-class: Zlib::StreamError
04569  *
04570  * Subclass of Zlib::Error
04571  *
04572  * When zlib returns a Z_STREAM_ERROR,
04573  * usually if the stream state was inconsistent.
04574  *
04575  */
04576 
04577 /*
04578  * Document-class: Zlib::BufError
04579  *
04580  * Subclass of Zlib::Error when zlib returns a Z_BUF_ERROR.
04581  *
04582  * Usually if no progress is possible.
04583  *
04584  */
04585 
04586 /*
04587  * Document-class: Zlib::DataError
04588  *
04589  * Subclass of Zlib::Error when zlib returns a Z_DATA_ERROR.
04590  *
04591  * Usually if a stream was prematurely freed.
04592  *
04593  */
04594 
04595 /*
04596  * Document-class: Zlib::GzipFile::Error
04597  *
04598  * Base class of errors that occur when processing GZIP files.
04599  */
04600 
04601 /*
04602  * Document-class: Zlib::GzipFile::NoFooter
04603  *
04604  * Raised when gzip file footer is not found.
04605  */
04606 
04607 /*
04608  * Document-class: Zlib::GzipFile::CRCError
04609  *
04610  * Raised when the CRC checksum recorded in gzip file footer is not equivalent
04611  * to the CRC checksum of the actual uncompressed data.
04612  */
04613 
04614 /*
04615  * Document-class: Zlib::GzipFile::LengthError
04616  *
04617  * Raised when the data length recorded in the gzip file footer is not equivalent
04618  * to the length of the actual uncompressed data.
04619  */
04620 
04621 
04622