• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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

Generated on Wed Sep 8 2010 09:55:44 for Ruby by  doxygen 1.7.1