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