• 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 32388 2011-07-03 13:41:50Z yugui $
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 ((uint32_t)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 extern VALUE rb_str_resurrect(VALUE str);
02392 
02393 static VALUE
02394 gzfile_reader_get_unused(struct gzfile *gz)
02395 {
02396     VALUE str;
02397 
02398     if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
02399     if (!GZFILE_IS_FINISHED(gz)) return Qnil;
02400     if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02401         gzfile_check_footer(gz);
02402     }
02403     if (NIL_P(gz->z.input)) return Qnil;
02404 
02405     str = rb_str_resurrect(gz->z.input);
02406     OBJ_TAINT(str);  /* for safe */
02407     return str;
02408 }
02409 
02410 static struct gzfile *
02411 get_gzfile(VALUE obj)
02412 {
02413     struct gzfile *gz;
02414 
02415     Data_Get_Struct(obj, struct gzfile, gz);
02416     if (!ZSTREAM_IS_READY(&gz->z)) {
02417         rb_raise(cGzError, "closed gzip stream");
02418     }
02419     return gz;
02420 }
02421 
02422 
02423 /* ------------------------------------------------------------------------- */
02424 
02425 /*
02426  * Document-class: Zlib::GzipFile
02427  *
02428  * Zlib::GzipFile is an abstract class for handling a gzip formatted
02429  * compressed file. The operations are defined in the subclasses,
02430  * Zlib::GzipReader for reading, and Zlib::GzipWriter for writing.
02431  *
02432  * GzipReader should be used by associating an IO, or IO-like, object.
02433  */
02434 
02435 
02436 static VALUE
02437 gzfile_ensure_close(VALUE obj)
02438 {
02439     struct gzfile *gz;
02440 
02441     Data_Get_Struct(obj, struct gzfile, gz);
02442     if (ZSTREAM_IS_READY(&gz->z)) {
02443         gzfile_close(gz, 1);
02444     }
02445     return Qnil;
02446 }
02447 
02448 /*
02449  * call-seq: Zlib::GzipFile.wrap(io) { |gz| ... }
02450  *
02451  * Creates a GzipFile object associated with +io+, and
02452  * executes the block with the newly created GzipFile object,
02453  * just like File.open. The GzipFile object will be closed
02454  * automatically after executing the block. If you want to keep
02455  * the associated IO object opening, you may call
02456  * +Zlib::GzipFile#finish+ method in the block.
02457  */
02458 static VALUE
02459 rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
02460 {
02461     VALUE obj = rb_class_new_instance(argc, argv, klass);
02462 
02463     if (rb_block_given_p()) {
02464         return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
02465     }
02466     else {
02467         return obj;
02468     }
02469 }
02470 
02471 /*
02472  * See Zlib::GzipReader#open and Zlib::GzipWriter#open.
02473  */
02474 static VALUE
02475 gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
02476 {
02477     VALUE io, filename;
02478 
02479     if (argc < 1) {
02480         rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
02481     }
02482     filename = argv[0];
02483     io = rb_file_open_str(filename, mode);
02484     argv[0] = io;
02485     return rb_gzfile_s_wrap(argc, argv, klass);
02486 }
02487 
02488 /*
02489  * Same as IO.
02490  */
02491 static VALUE
02492 rb_gzfile_to_io(VALUE obj)
02493 {
02494     return get_gzfile(obj)->io;
02495 }
02496 
02497 /*
02498  * Returns CRC value of the uncompressed data.
02499  */
02500 static VALUE
02501 rb_gzfile_crc(VALUE obj)
02502 {
02503     return rb_uint2inum(get_gzfile(obj)->crc);
02504 }
02505 
02506 /*
02507  * Returns last modification time recorded in the gzip file header.
02508  */
02509 static VALUE
02510 rb_gzfile_mtime(VALUE obj)
02511 {
02512     return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
02513 }
02514 
02515 /*
02516  * Returns compression level.
02517  */
02518 static VALUE
02519 rb_gzfile_level(VALUE obj)
02520 {
02521     return INT2FIX(get_gzfile(obj)->level);
02522 }
02523 
02524 /*
02525  * Returns OS code number recorded in the gzip file header.
02526  */
02527 static VALUE
02528 rb_gzfile_os_code(VALUE obj)
02529 {
02530     return INT2FIX(get_gzfile(obj)->os_code);
02531 }
02532 
02533 /*
02534  * Returns original filename recorded in the gzip file header, or +nil+ if
02535  * original filename is not present.
02536  */
02537 static VALUE
02538 rb_gzfile_orig_name(VALUE obj)
02539 {
02540     VALUE str = get_gzfile(obj)->orig_name;
02541     if (!NIL_P(str)) {
02542         str = rb_str_dup(str);
02543     }
02544     OBJ_TAINT(str);  /* for safe */
02545     return str;
02546 }
02547 
02548 /*
02549  * Returns comments recorded in the gzip file header, or nil if the comments
02550  * is not present.
02551  */
02552 static VALUE
02553 rb_gzfile_comment(VALUE obj)
02554 {
02555     VALUE str = get_gzfile(obj)->comment;
02556     if (!NIL_P(str)) {
02557         str = rb_str_dup(str);
02558     }
02559     OBJ_TAINT(str);  /* for safe */
02560     return str;
02561 }
02562 
02563 /*
02564  * ???
02565  */
02566 static VALUE
02567 rb_gzfile_lineno(VALUE obj)
02568 {
02569     return INT2NUM(get_gzfile(obj)->lineno);
02570 }
02571 
02572 /*
02573  * ???
02574  */
02575 static VALUE
02576 rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
02577 {
02578     struct gzfile *gz = get_gzfile(obj);
02579     gz->lineno = NUM2INT(lineno);
02580     return lineno;
02581 }
02582 
02583 /*
02584  * ???
02585  */
02586 static VALUE
02587 rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
02588 {
02589     struct gzfile *gz = get_gzfile(obj);
02590     VALUE val;
02591 
02592     if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
02593         rb_raise(cGzError, "header is already written");
02594     }
02595 
02596     if (FIXNUM_P(mtime)) {
02597         gz->mtime = FIX2INT(mtime);
02598     }
02599     else {
02600         val = rb_Integer(mtime);
02601         gz->mtime = FIXNUM_P(val) ? FIX2UINT(val) : rb_big2ulong(val);
02602     }
02603     return mtime;
02604 }
02605 
02606 /*
02607  * ???
02608  */
02609 static VALUE
02610 rb_gzfile_set_orig_name(VALUE obj, VALUE str)
02611 {
02612     struct gzfile *gz = get_gzfile(obj);
02613     VALUE s;
02614     char *p;
02615 
02616     if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
02617         rb_raise(cGzError, "header is already written");
02618     }
02619     s = rb_str_dup(rb_str_to_str(str));
02620     p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
02621     if (p) {
02622         rb_str_resize(s, p - RSTRING_PTR(s));
02623     }
02624     gz->orig_name = s;
02625     return str;
02626 }
02627 
02628 /*
02629  * ???
02630  */
02631 static VALUE
02632 rb_gzfile_set_comment(VALUE obj, VALUE str)
02633 {
02634     struct gzfile *gz = get_gzfile(obj);
02635     VALUE s;
02636     char *p;
02637 
02638     if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
02639         rb_raise(cGzError, "header is already written");
02640     }
02641     s = rb_str_dup(rb_str_to_str(str));
02642     p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
02643     if (p) {
02644         rb_str_resize(s, p - RSTRING_PTR(s));
02645     }
02646     gz->comment = s;
02647     return str;
02648 }
02649 
02650 /*
02651  * Closes the GzipFile object. This method calls close method of the
02652  * associated IO object. Returns the associated IO object.
02653  */
02654 static VALUE
02655 rb_gzfile_close(VALUE obj)
02656 {
02657     struct gzfile *gz = get_gzfile(obj);
02658     VALUE io;
02659 
02660     io = gz->io;
02661     gzfile_close(gz, 1);
02662     return io;
02663 }
02664 
02665 /*
02666  * Closes the GzipFile object. Unlike Zlib::GzipFile#close, this method never
02667  * calls the close method of the associated IO object. Returns the associated IO
02668  * object.
02669  */
02670 static VALUE
02671 rb_gzfile_finish(VALUE obj)
02672 {
02673     struct gzfile *gz = get_gzfile(obj);
02674     VALUE io;
02675 
02676     io = gz->io;
02677     gzfile_close(gz, 0);
02678     return io;
02679 }
02680 
02681 /*
02682  * Same as IO.
02683  */
02684 static VALUE
02685 rb_gzfile_closed_p(VALUE obj)
02686 {
02687     struct gzfile *gz;
02688     Data_Get_Struct(obj, struct gzfile, gz);
02689     return NIL_P(gz->io) ? Qtrue : Qfalse;
02690 }
02691 
02692 /*
02693  * ???
02694  */
02695 static VALUE
02696 rb_gzfile_eof_p(VALUE obj)
02697 {
02698     struct gzfile *gz = get_gzfile(obj);
02699     return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
02700 }
02701 
02702 /*
02703  * Same as IO.
02704  */
02705 static VALUE
02706 rb_gzfile_sync(VALUE obj)
02707 {
02708     return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
02709 }
02710 
02711 /*
02712  * call-seq: sync = flag
02713  *
02714  * Same as IO.  If flag is +true+, the associated IO object must respond to the
02715  * +flush+ method.  While +sync+ mode is +true+, the compression ratio
02716  * decreases sharply.
02717  */
02718 static VALUE
02719 rb_gzfile_set_sync(VALUE obj, VALUE mode)
02720 {
02721     struct gzfile *gz = get_gzfile(obj);
02722 
02723     if (RTEST(mode)) {
02724         gz->z.flags |= GZFILE_FLAG_SYNC;
02725     }
02726     else {
02727         gz->z.flags &= ~GZFILE_FLAG_SYNC;
02728     }
02729     return mode;
02730 }
02731 
02732 /*
02733  * ???
02734  */
02735 static VALUE
02736 rb_gzfile_total_in(VALUE obj)
02737 {
02738     return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
02739 }
02740 
02741 /*
02742  * ???
02743  */
02744 static VALUE
02745 rb_gzfile_total_out(VALUE obj)
02746 {
02747     struct gzfile *gz = get_gzfile(obj);
02748     return rb_uint2inum(gz->z.stream.total_out - gz->z.buf_filled);
02749 }
02750 
02751 /*
02752  * Document-method: path
02753  *
02754  * call-seq: path
02755  *
02756  * Returns the path string of the associated IO-like object.  This
02757  * method is only defined when the IO-like object responds to #path().
02758  */
02759 static VALUE
02760 rb_gzfile_path(VALUE obj)
02761 {
02762     struct gzfile *gz;
02763     Data_Get_Struct(obj, struct gzfile, gz);
02764     return gz->path;
02765 }
02766 
02767 static void
02768 rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
02769 {
02770     if (!NIL_P(opts)) {
02771         rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2);
02772     }
02773     if (gz->enc2) {
02774         gz->ecflags = rb_econv_prepare_opts(opts, &opts);
02775         gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
02776                                     gz->ecflags, opts);
02777         gz->ecopts = opts;
02778     }
02779 }
02780 
02781 /* ------------------------------------------------------------------------- */
02782 
02783 /*
02784  * Document-class: Zlib::GzipWriter
02785  *
02786  * Zlib::GzipWriter is a class for writing gzipped files.  GzipWriter should
02787  * be used with an instance of IO, or IO-like, object.
02788  *
02789  * For example:
02790  *
02791  *   Zlib::GzipWriter.open('hoge.gz') do |gz|
02792  *     gz.write 'jugemu jugemu gokou no surikire...'
02793  *   end
02794  *
02795  *   File.open('hoge.gz', 'w') do |f|
02796  *     gz = Zlib::GzipWriter.new(f)
02797  *     gz.write 'jugemu jugemu gokou no surikire...'
02798  *     gz.close
02799  *   end
02800  *
02801  *   # TODO: test these.  Are they equivalent?  Can GzipWriter.new take a
02802  *   # block?
02803  *
02804  * NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close
02805  * GzipWriter objects by Zlib::GzipWriter#close etc.  Otherwise, GzipWriter
02806  * will be not able to write the gzip footer and will generate a broken gzip
02807  * file.
02808  */
02809 
02810 static VALUE
02811 rb_gzwriter_s_allocate(VALUE klass)
02812 {
02813     return gzfile_writer_new(klass);
02814 }
02815 
02816 /*
02817  * call-seq: Zlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... }
02818  *
02819  * Opens a file specified by +filename+ for writing gzip compressed data, and
02820  * returns a GzipWriter object associated with that file.  Further details of
02821  * this method are found in Zlib::GzipWriter.new and Zlib::GzipFile.wrap.
02822  */
02823 static VALUE
02824 rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
02825 {
02826     return gzfile_s_open(argc, argv, klass, "wb");
02827 }
02828 
02829 /*
02830  * call-seq: Zlib::GzipWriter.new(io, level, strategy)
02831  *
02832  * Creates a GzipWriter object associated with +io+. +level+ and +strategy+
02833  * should be the same as the arguments of Zlib::Deflate.new.  The GzipWriter
02834  * object writes gzipped data to +io+.  At least, +io+ must respond to the
02835  * +write+ method that behaves same as write method in IO class.
02836  */
02837 static VALUE
02838 rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
02839 {
02840     struct gzfile *gz;
02841     VALUE io, level, strategy, opt = Qnil;
02842     int err;
02843 
02844     if (argc > 1) {
02845         opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
02846         if (!NIL_P(opt)) argc--;
02847     }
02848 
02849     rb_scan_args(argc, argv, "12", &io, &level, &strategy);
02850     Data_Get_Struct(obj, struct gzfile, gz);
02851 
02852     /* this is undocumented feature of zlib */
02853     gz->level = ARG_LEVEL(level);
02854     err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
02855                        -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
02856     if (err != Z_OK) {
02857         raise_zlib_error(err, gz->z.stream.msg);
02858     }
02859     gz->io = io;
02860     ZSTREAM_READY(&gz->z);
02861     rb_gzfile_ecopts(gz, opt);
02862 
02863     if (rb_respond_to(io, id_path)) {
02864         gz->path = rb_funcall(gz->io, id_path, 0);
02865         rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
02866     }
02867 
02868     return obj;
02869 }
02870 
02871 /*
02872  * call-seq: flush(flush=nil)
02873  *
02874  * Flushes all the internal buffers of the GzipWriter object.  The meaning of
02875  * +flush+ is same as in Zlib::Deflate#deflate.  <tt>Zlib::SYNC_FLUSH</tt> is used if
02876  * +flush+ is omitted.  It is no use giving flush <tt>Zlib::NO_FLUSH</tt>.
02877  */
02878 static VALUE
02879 rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
02880 {
02881     struct gzfile *gz = get_gzfile(obj);
02882     VALUE v_flush;
02883     int flush;
02884 
02885     rb_scan_args(argc, argv, "01", &v_flush);
02886 
02887     flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
02888     if (flush != Z_NO_FLUSH) {  /* prevent Z_BUF_ERROR */
02889         zstream_run(&gz->z, (Bytef*)"", 0, flush);
02890     }
02891 
02892     gzfile_write_raw(gz);
02893     if (rb_respond_to(gz->io, id_flush)) {
02894         rb_funcall(gz->io, id_flush, 0);
02895     }
02896     return obj;
02897 }
02898 
02899 /*
02900  * Same as IO.
02901  */
02902 static VALUE
02903 rb_gzwriter_write(VALUE obj, VALUE str)
02904 {
02905     struct gzfile *gz = get_gzfile(obj);
02906 
02907     if (TYPE(str) != T_STRING)
02908         str = rb_obj_as_string(str);
02909     if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
02910         str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
02911     }
02912     gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
02913     return INT2FIX(RSTRING_LEN(str));
02914 }
02915 
02916 /*
02917  * Same as IO.
02918  */
02919 static VALUE
02920 rb_gzwriter_putc(VALUE obj, VALUE ch)
02921 {
02922     struct gzfile *gz = get_gzfile(obj);
02923     char c = NUM2CHR(ch);
02924 
02925     gzfile_write(gz, (Bytef*)&c, 1);
02926     return ch;
02927 }
02928 
02929 
02930 
02931 /*
02932  * Document-method: <<
02933  * Same as IO.
02934  */
02935 #define rb_gzwriter_addstr  rb_io_addstr
02936 /*
02937  * Document-method: printf
02938  * Same as IO.
02939  */
02940 #define rb_gzwriter_printf  rb_io_printf
02941 /*
02942  * Document-method: print
02943  * Same as IO.
02944  */
02945 #define rb_gzwriter_print  rb_io_print
02946 /*
02947  * Document-method: puts
02948  * Same as IO.
02949  */
02950 #define rb_gzwriter_puts  rb_io_puts
02951 
02952 
02953 /* ------------------------------------------------------------------------- */
02954 
02955 /*
02956  * Document-class: Zlib::GzipReader
02957  *
02958  * Zlib::GzipReader is the class for reading a gzipped file.  GzipReader should
02959  * be used an IO, or -IO-lie, object.
02960  *
02961  *   Zlib::GzipReader.open('hoge.gz') {|gz|
02962  *     print gz.read
02963  *   }
02964  *
02965  *   File.open('hoge.gz') do |f|
02966  *     gz = Zlib::GzipReader.new(f)
02967  *     print gz.read
02968  *     gz.close
02969  *   end
02970  *
02971  *   # TODO: test these.  Are they equivalent?  Can GzipReader.new take a
02972  *   # block?
02973  *
02974  * == Method Catalogue
02975  *
02976  * The following methods in Zlib::GzipReader are just like their counterparts
02977  * in IO, but they raise Zlib::Error or Zlib::GzipFile::Error exception if an
02978  * error was found in the gzip file.
02979  * - #each
02980  * - #each_line
02981  * - #each_byte
02982  * - #gets
02983  * - #getc
02984  * - #lineno
02985  * - #lineno=
02986  * - #read
02987  * - #readchar
02988  * - #readline
02989  * - #readlines
02990  * - #ungetc
02991  *
02992  * Be careful of the footer of the gzip file. A gzip file has the checksum of
02993  * pre-compressed data in its footer. GzipReader checks all uncompressed data
02994  * against that checksum at the following cases, and if it fails, raises
02995  * <tt>Zlib::GzipFile::NoFooter</tt>, <tt>Zlib::GzipFile::CRCError</tt>, or
02996  * <tt>Zlib::GzipFile::LengthError</tt> exception.
02997  *
02998  * - When an reading request is received beyond the end of file (the end of
02999  *   compressed data). That is, when Zlib::GzipReader#read,
03000  *   Zlib::GzipReader#gets, or some other methods for reading returns nil.
03001  * - When Zlib::GzipFile#close method is called after the object reaches the
03002  *   end of file.
03003  * - When Zlib::GzipReader#unused method is called after the object reaches
03004  *   the end of file.
03005  *
03006  * The rest of the methods are adequately described in their own
03007  * documentation.
03008  */
03009 
03010 static VALUE
03011 rb_gzreader_s_allocate(VALUE klass)
03012 {
03013     return gzfile_reader_new(klass);
03014 }
03015 
03016 /*
03017  * call-seq: Zlib::GzipReader.open(filename) {|gz| ... }
03018  *
03019  * Opens a file specified by +filename+ as a gzipped file, and returns a
03020  * GzipReader object associated with that file.  Further details of this method
03021  * are in Zlib::GzipReader.new and ZLib::GzipFile.wrap.
03022  */
03023 static VALUE
03024 rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
03025 {
03026     return gzfile_s_open(argc, argv, klass, "rb");
03027 }
03028 
03029 /*
03030  * call-seq: Zlib::GzipReader.new(io)
03031  *
03032  * Creates a GzipReader object associated with +io+. The GzipReader object reads
03033  * gzipped data from +io+, and parses/decompresses them.  At least, +io+ must have
03034  * a +read+ method that behaves same as the +read+ method in IO class.
03035  *
03036  * If the gzip file header is incorrect, raises an Zlib::GzipFile::Error
03037  * exception.
03038  */
03039 static VALUE
03040 rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
03041 {
03042     VALUE io, opt = Qnil;
03043     struct gzfile *gz;
03044     int err;
03045 
03046     Data_Get_Struct(obj, struct gzfile, gz);
03047     if (argc > 1) {
03048         opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
03049         if (!NIL_P(opt)) argc--;
03050     }
03051     rb_scan_args(argc, argv, "1", &io);
03052 
03053     /* this is undocumented feature of zlib */
03054     err = inflateInit2(&gz->z.stream, -MAX_WBITS);
03055     if (err != Z_OK) {
03056         raise_zlib_error(err, gz->z.stream.msg);
03057     }
03058     gz->io = io;
03059     ZSTREAM_READY(&gz->z);
03060     gzfile_read_header(gz);
03061     rb_gzfile_ecopts(gz, opt);
03062 
03063     if (rb_respond_to(io, id_path)) {
03064         gz->path = rb_funcall(gz->io, id_path, 0);
03065         rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
03066     }
03067 
03068     return obj;
03069 }
03070 
03071 /*
03072  * Resets the position of the file pointer to the point created the GzipReader
03073  * object.  The associated IO object needs to respond to the +seek+ method.
03074  */
03075 static VALUE
03076 rb_gzreader_rewind(VALUE obj)
03077 {
03078     struct gzfile *gz = get_gzfile(obj);
03079     gzfile_reader_rewind(gz);
03080     return INT2FIX(0);
03081 }
03082 
03083 /*
03084  * Returns the rest of the data which had read for parsing gzip format, or
03085  * +nil+ if the whole gzip file is not parsed yet.
03086  */
03087 static VALUE
03088 rb_gzreader_unused(VALUE obj)
03089 {
03090     struct gzfile *gz;
03091     Data_Get_Struct(obj, struct gzfile, gz);
03092     return gzfile_reader_get_unused(gz);
03093 }
03094 
03095 /*
03096  * See Zlib::GzipReader documentation for a description.
03097  */
03098 static VALUE
03099 rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
03100 {
03101     struct gzfile *gz = get_gzfile(obj);
03102     VALUE vlen;
03103     int len;
03104 
03105     rb_scan_args(argc, argv, "01", &vlen);
03106     if (NIL_P(vlen)) {
03107         return gzfile_read_all(gz);
03108     }
03109 
03110     len = NUM2INT(vlen);
03111     if (len < 0) {
03112         rb_raise(rb_eArgError, "negative length %d given", len);
03113     }
03114     return gzfile_read(gz, len);
03115 }
03116 
03117 /*
03118  *  call-seq:
03119  *     gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
03120  *
03121  *  Reads at most <i>maxlen</i> bytes from the gziped stream but
03122  *  it blocks only if <em>gzipreader</em> has no data immediately available.
03123  *  If the optional <i>outbuf</i> argument is present,
03124  *  it must reference a String, which will receive the data.
03125  *  It raises <code>EOFError</code> on end of file.
03126  */
03127 static VALUE
03128 rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
03129 {
03130     struct gzfile *gz = get_gzfile(obj);
03131     VALUE vlen, outbuf;
03132     int len;
03133 
03134     rb_scan_args(argc, argv, "11", &vlen, &outbuf);
03135 
03136     len = NUM2INT(vlen);
03137     if (len < 0) {
03138         rb_raise(rb_eArgError, "negative length %d given", len);
03139     }
03140     if (!NIL_P(outbuf))
03141         Check_Type(outbuf, T_STRING);
03142     return gzfile_readpartial(gz, len, outbuf);
03143 }
03144 
03145 /*
03146  * See Zlib::GzipReader documentation for a description.
03147  */
03148 static VALUE
03149 rb_gzreader_getc(VALUE obj)
03150 {
03151     struct gzfile *gz = get_gzfile(obj);
03152 
03153     return gzfile_getc(gz);
03154 }
03155 
03156 /*
03157  * See Zlib::GzipReader documentation for a description.
03158  */
03159 static VALUE
03160 rb_gzreader_readchar(VALUE obj)
03161 {
03162     VALUE dst;
03163     dst = rb_gzreader_getc(obj);
03164     if (NIL_P(dst)) {
03165         rb_raise(rb_eEOFError, "end of file reached");
03166     }
03167     return dst;
03168 }
03169 
03170 /*
03171  * See Zlib::GzipReader documentation for a description.
03172  */
03173 static VALUE
03174 rb_gzreader_getbyte(VALUE obj)
03175 {
03176     struct gzfile *gz = get_gzfile(obj);
03177     VALUE dst;
03178 
03179     dst = gzfile_read(gz, 1);
03180     if (!NIL_P(dst)) {
03181         dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
03182     }
03183     return dst;
03184 }
03185 
03186 /*
03187  * See Zlib::GzipReader documentation for a description.
03188  */
03189 static VALUE
03190 rb_gzreader_readbyte(VALUE obj)
03191 {
03192     VALUE dst;
03193     dst = rb_gzreader_getbyte(obj);
03194     if (NIL_P(dst)) {
03195         rb_raise(rb_eEOFError, "end of file reached");
03196     }
03197     return dst;
03198 }
03199 
03200 /*
03201  * See Zlib::GzipReader documentation for a description.
03202  */
03203 static VALUE
03204 rb_gzreader_each_char(VALUE obj)
03205 {
03206     VALUE c;
03207 
03208     RETURN_ENUMERATOR(obj, 0, 0);
03209 
03210     while (!NIL_P(c = rb_gzreader_getc(obj))) {
03211         rb_yield(c);
03212     }
03213     return Qnil;
03214 }
03215 
03216 /*
03217  * See Zlib::GzipReader documentation for a description.
03218  */
03219 static VALUE
03220 rb_gzreader_each_byte(VALUE obj)
03221 {
03222     VALUE c;
03223 
03224     RETURN_ENUMERATOR(obj, 0, 0);
03225 
03226     while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
03227         rb_yield(c);
03228     }
03229     return Qnil;
03230 }
03231 
03232 /*
03233  * See Zlib::GzipReader documentation for a description.
03234  */
03235 static VALUE
03236 rb_gzreader_ungetc(VALUE obj, VALUE s)
03237 {
03238     struct gzfile *gz;
03239 
03240     if (FIXNUM_P(s))
03241         return rb_gzreader_ungetbyte(obj, s);
03242     gz = get_gzfile(obj);
03243     StringValue(s);
03244     if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
03245         s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
03246     }
03247     gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
03248     return Qnil;
03249 }
03250 
03251 /*
03252  * See Zlib::GzipReader documentation for a description.
03253  */
03254 static VALUE
03255 rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
03256 {
03257     struct gzfile *gz = get_gzfile(obj);
03258     gzfile_ungetbyte(gz, NUM2CHR(ch));
03259     return Qnil;
03260 }
03261 
03262 static void
03263 gzreader_skip_linebreaks(struct gzfile *gz)
03264 {
03265     VALUE str;
03266     char *p;
03267     int n;
03268 
03269     while (gz->z.buf_filled == 0) {
03270         if (GZFILE_IS_FINISHED(gz)) return;
03271         gzfile_read_more(gz);
03272     }
03273     n = 0;
03274     p = RSTRING_PTR(gz->z.buf);
03275 
03276     while (n++, *(p++) == '\n') {
03277         if (n >= gz->z.buf_filled) {
03278             str = zstream_detach_buffer(&gz->z);
03279             gzfile_calc_crc(gz, str);
03280             while (gz->z.buf_filled == 0) {
03281                 if (GZFILE_IS_FINISHED(gz)) return;
03282                 gzfile_read_more(gz);
03283             }
03284             n = 0;
03285             p = RSTRING_PTR(gz->z.buf);
03286         }
03287     }
03288 
03289     str = zstream_shift_buffer(&gz->z, n - 1);
03290     gzfile_calc_crc(gz, str);
03291 }
03292 
03293 static void
03294 rscheck(const char *rsptr, long rslen, VALUE rs)
03295 {
03296     if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
03297         rb_raise(rb_eRuntimeError, "rs modified");
03298 }
03299 
03300 static VALUE
03301 gzreader_gets(int argc, VALUE *argv, VALUE obj)
03302 {
03303     struct gzfile *gz = get_gzfile(obj);
03304     volatile VALUE rs;
03305     VALUE dst;
03306     const char *rsptr;
03307     char *p, *res;
03308     long rslen, n;
03309     int rspara;
03310 
03311     if (argc == 0) {
03312         rs = rb_rs;
03313     }
03314     else {
03315         rb_scan_args(argc, argv, "1", &rs);
03316         if (!NIL_P(rs)) {
03317             Check_Type(rs, T_STRING);
03318         }
03319     }
03320 
03321     if (NIL_P(rs)) {
03322         dst = gzfile_read_all(gz);
03323         if (RSTRING_LEN(dst) != 0) gz->lineno++;
03324         else
03325             return Qnil;
03326         return dst;
03327     }
03328 
03329     if (RSTRING_LEN(rs) == 0) {
03330         rsptr = "\n\n";
03331         rslen = 2;
03332         rspara = 1;
03333     } else {
03334         rsptr = RSTRING_PTR(rs);
03335         rslen = RSTRING_LEN(rs);
03336         rspara = 0;
03337     }
03338 
03339     if (rspara) {
03340         gzreader_skip_linebreaks(gz);
03341     }
03342 
03343     while (gz->z.buf_filled < rslen) {
03344         if (ZSTREAM_IS_FINISHED(&gz->z)) {
03345             if (gz->z.buf_filled > 0) gz->lineno++;
03346             return gzfile_read(gz, rslen);
03347         }
03348         gzfile_read_more(gz);
03349     }
03350 
03351     p = RSTRING_PTR(gz->z.buf);
03352     n = rslen;
03353     for (;;) {
03354         if (n > gz->z.buf_filled) {
03355             if (ZSTREAM_IS_FINISHED(&gz->z)) break;
03356             gzfile_read_more(gz);
03357             p = RSTRING_PTR(gz->z.buf) + n - rslen;
03358         }
03359         if (!rspara) rscheck(rsptr, rslen, rs);
03360         res = memchr(p, rsptr[0], (gz->z.buf_filled - n + 1));
03361         if (!res) {
03362             n = gz->z.buf_filled + 1;
03363         } else {
03364             n += (long)(res - p);
03365             p = res;
03366             if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
03367             p++, n++;
03368         }
03369     }
03370 
03371     gz->lineno++;
03372     dst = gzfile_read(gz, n);
03373     if (rspara) {
03374         gzreader_skip_linebreaks(gz);
03375     }
03376 
03377     return gzfile_newstr(gz, dst);
03378 }
03379 
03380 /*
03381  * See Zlib::GzipReader documentation for a description.
03382  */
03383 static VALUE
03384 rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
03385 {
03386     VALUE dst;
03387     dst = gzreader_gets(argc, argv, obj);
03388     if (!NIL_P(dst)) {
03389         rb_lastline_set(dst);
03390     }
03391     return dst;
03392 }
03393 
03394 /*
03395  * See Zlib::GzipReader documentation for a description.
03396  */
03397 static VALUE
03398 rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
03399 {
03400     VALUE dst;
03401     dst = rb_gzreader_gets(argc, argv, obj);
03402     if (NIL_P(dst)) {
03403         rb_raise(rb_eEOFError, "end of file reached");
03404     }
03405     return dst;
03406 }
03407 
03408 /*
03409  * See Zlib::GzipReader documentation for a description.
03410  */
03411 static VALUE
03412 rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
03413 {
03414     VALUE str;
03415 
03416     RETURN_ENUMERATOR(obj, 0, 0);
03417 
03418     while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
03419         rb_yield(str);
03420     }
03421     return obj;
03422 }
03423 
03424 /*
03425  * See Zlib::GzipReader documentation for a description.
03426  */
03427 static VALUE
03428 rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
03429 {
03430     VALUE str, dst;
03431     dst = rb_ary_new();
03432     while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
03433         rb_ary_push(dst, str);
03434     }
03435     return dst;
03436 }
03437 
03438 #endif /* GZIP_SUPPORT */
03439 
03440 
03441 
03442 /*
03443  * The Zlib module contains several classes for compressing and decompressing
03444  * streams, and for working with "gzip" files.
03445  *
03446  * == Classes
03447  *
03448  * Following are the classes that are most likely to be of interest to the
03449  * user:
03450  * Zlib::Inflate
03451  * Zlib::Deflate
03452  * Zlib::GzipReader
03453  * Zlib::GzipWriter
03454  *
03455  * There are two important base classes for the classes above: Zlib::ZStream
03456  * and Zlib::GzipFile.  Everything else is an error class.
03457  *
03458  * == Constants
03459  *
03460  * Here's a list.
03461  *
03462  *   Zlib::VERSION
03463  *       The Ruby/zlib version string.
03464  *
03465  *   Zlib::ZLIB_VERSION
03466  *       The string which represents the version of zlib.h.
03467  *
03468  *   Zlib::BINARY
03469  *   Zlib::ASCII
03470  *   Zlib::UNKNOWN
03471  *       The integers representing data types which Zlib::ZStream#data_type
03472  *       method returns.
03473  *
03474  *   Zlib::NO_COMPRESSION
03475  *   Zlib::BEST_SPEED
03476  *   Zlib::BEST_COMPRESSION
03477  *   Zlib::DEFAULT_COMPRESSION
03478  *       The integers representing compression levels which are an argument
03479  *       for Zlib::Deflate.new, Zlib::Deflate#deflate, and so on.
03480  *
03481  *   Zlib::FILTERED
03482  *   Zlib::HUFFMAN_ONLY
03483  *   Zlib::DEFAULT_STRATEGY
03484  *       The integers representing compression methods which are an argument
03485  *       for Zlib::Deflate.new and Zlib::Deflate#params.
03486  *
03487  *   Zlib::DEF_MEM_LEVEL
03488  *   Zlib::MAX_MEM_LEVEL
03489  *       The integers representing memory levels which are an argument for
03490  *       Zlib::Deflate.new, Zlib::Deflate#params, and so on.
03491  *
03492  *   Zlib::MAX_WBITS
03493  *       The default value of windowBits which is an argument for
03494  *       Zlib::Deflate.new and Zlib::Inflate.new.
03495  *
03496  *   Zlib::NO_FLUSH
03497  *   Zlib::SYNC_FLUSH
03498  *   Zlib::FULL_FLUSH
03499  *   Zlib::FINISH
03500  *       The integers to control the output of the deflate stream, which are
03501  *       an argument for Zlib::Deflate#deflate and so on.
03502  *
03503  *   Zlib::OS_CODE
03504  *   Zlib::OS_MSDOS
03505  *   Zlib::OS_AMIGA
03506  *   Zlib::OS_VMS
03507  *   Zlib::OS_UNIX
03508  *   Zlib::OS_VMCMS
03509  *   Zlib::OS_ATARI
03510  *   Zlib::OS_OS2
03511  *   Zlib::OS_MACOS
03512  *   Zlib::OS_ZSYSTEM
03513  *   Zlib::OS_CPM
03514  *   Zlib::OS_TOPS20
03515  *   Zlib::OS_WIN32
03516  *   Zlib::OS_QDOS
03517  *   Zlib::OS_RISCOS
03518  *   Zlib::OS_UNKNOWN
03519  *       The return values of Zlib::GzipFile#os_code method.
03520  */
03521 void
03522 Init_zlib()
03523 {
03524     VALUE mZlib, cZStream, cDeflate, cInflate;
03525 #if GZIP_SUPPORT
03526     VALUE cGzipFile, cGzipWriter, cGzipReader;
03527 #endif
03528 
03529     mZlib = rb_define_module("Zlib");
03530 
03531     cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
03532     cStreamEnd    = rb_define_class_under(mZlib, "StreamEnd", cZError);
03533     cNeedDict     = rb_define_class_under(mZlib, "NeedDict", cZError);
03534     cDataError    = rb_define_class_under(mZlib, "DataError", cZError);
03535     cStreamError  = rb_define_class_under(mZlib, "StreamError", cZError);
03536     cMemError     = rb_define_class_under(mZlib, "MemError", cZError);
03537     cBufError     = rb_define_class_under(mZlib, "BufError", cZError);
03538     cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
03539 
03540     rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
03541     rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
03542     rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
03543     rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
03544     rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
03545     rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
03546 
03547     rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
03548     rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
03549 
03550     cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
03551     rb_undef_alloc_func(cZStream);
03552     rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
03553     rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
03554     rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
03555     rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
03556     rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
03557     rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
03558     rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
03559     rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
03560     rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
03561     rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
03562     rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
03563     rb_define_method(cZStream, "close", rb_zstream_end, 0);
03564     rb_define_method(cZStream, "end", rb_zstream_end, 0);
03565     rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
03566     rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
03567     rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
03568     rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
03569 
03570     rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
03571     rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
03572     rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
03573 
03574     cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
03575     rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
03576     rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
03577     rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
03578     rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
03579     rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
03580     rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
03581     rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
03582     rb_define_method(cDeflate, "params", rb_deflate_params, 2);
03583     rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
03584 
03585     cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
03586     rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
03587     rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
03588     rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
03589     rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
03590     rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
03591     rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
03592     rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
03593     rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
03594 
03595     rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
03596     rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
03597     rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
03598     rb_define_const(mZlib, "DEFAULT_COMPRESSION",
03599                     INT2FIX(Z_DEFAULT_COMPRESSION));
03600 
03601     rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
03602     rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
03603     rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
03604 
03605     rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
03606     rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
03607     rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
03608 
03609     rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
03610     rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
03611     rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
03612     rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
03613 
03614 #if GZIP_SUPPORT
03615     id_write = rb_intern("write");
03616     id_read = rb_intern("read");
03617     id_readpartial = rb_intern("readpartial");
03618     id_flush = rb_intern("flush");
03619     id_seek = rb_intern("seek");
03620     id_close = rb_intern("close");
03621     id_path = rb_intern("path");
03622 
03623     cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
03624     cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
03625 
03626     cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
03627     cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
03628     cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
03629 
03630     cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
03631     cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
03632     rb_include_module(cGzipReader, rb_mEnumerable);
03633 
03634     rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
03635     rb_undef_alloc_func(cGzipFile);
03636     rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
03637     rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
03638     rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
03639     rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
03640     rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
03641     rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
03642     rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
03643     rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
03644     rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
03645     rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
03646     rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
03647     rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
03648     rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
03649     rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
03650     rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
03651     rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
03652     rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
03653     rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
03654     rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
03655     rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
03656     rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
03657     rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
03658     rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
03659 
03660     rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
03661     rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
03662     rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
03663     rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
03664     rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
03665     rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
03666     rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
03667     rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
03668     rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
03669     rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
03670 
03671     rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
03672     rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
03673     rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
03674     rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
03675     rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
03676     rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
03677     rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
03678     rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
03679     rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
03680     rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
03681     rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
03682     rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
03683     rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
03684     rb_define_method(cGzipReader, "bytes", rb_gzreader_each_byte, 0);
03685     rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
03686     rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
03687     rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
03688     rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
03689     rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
03690     rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
03691     rb_define_method(cGzipReader, "lines", rb_gzreader_each, -1);
03692     rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
03693 
03694     rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
03695     rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
03696     rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
03697     rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
03698     rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
03699     rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
03700     rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
03701     rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
03702     rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
03703     rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
03704 
03705     rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
03706     rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
03707     rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
03708     rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
03709     rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
03710     rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
03711 
03712 #endif /* GZIP_SUPPORT */
03713 }
03714 
03715 /* Document error classes. */
03716 
03717 /*
03718  * Document-class: Zlib::Error
03719  *
03720  * The superclass for all exceptions raised by Ruby/zlib.
03721  *
03722  * The following exceptions are defined as subclasses of Zlib::Error. These
03723  * exceptions are raised when zlib library functions return with an error
03724  * status.
03725  *
03726  * - Zlib::StreamEnd
03727  * - Zlib::NeedDict
03728  * - Zlib::DataError
03729  * - Zlib::StreamError
03730  * - Zlib::MemError
03731  * - Zlib::BufError
03732  * - Zlib::VersionError
03733  *
03734  */
03735 
03736 /*
03737  * Document-class: Zlib::GzipFile::Error
03738  *
03739  * Base class of errors that occur when processing GZIP files.
03740  */
03741 
03742 /*
03743  * Document-class: Zlib::GzipFile::NoFooter
03744  *
03745  * Raised when gzip file footer is not found.
03746  */
03747 
03748 /*
03749  * Document-class: Zlib::GzipFile::CRCError
03750  *
03751  * Raised when the CRC checksum recorded in gzip file footer is not equivalent
03752  * to the CRC checksum of the actual uncompressed data.
03753  */
03754 
03755 /*
03756  * Document-class: Zlib::GzipFile::LengthError
03757  *
03758  * Raised when the data length recorded in the gzip file footer is not equivalent
03759  * to the length of the actual uncompressed data.
03760  */
03761 
03762 
03763 

Generated on Sat Jul 7 2012 15:29:17 for Ruby by  doxygen 1.7.1