Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/zlib/zlib.c

Go to the documentation of this file.

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