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