zlib 0.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +31 -4
- data/ext/zlib/extconf.rb +5 -1
- data/ext/zlib/zlib.c +430 -285
- data/zlib.gemspec +16 -4
- metadata +9 -10
- data/.travis.yml +0 -5
    
        data/ext/zlib/zlib.c
    CHANGED
    
    | @@ -25,7 +25,11 @@ | |
| 25 25 | 
             
            # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
         | 
| 26 26 | 
             
            #endif
         | 
| 27 27 |  | 
| 28 | 
            -
            #define RUBY_ZLIB_VERSION | 
| 28 | 
            +
            #define RUBY_ZLIB_VERSION "2.0.0"
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            #ifndef RB_PASS_CALLED_KEYWORDS
         | 
| 31 | 
            +
            # define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
         | 
| 32 | 
            +
            #endif
         | 
| 29 33 |  | 
| 30 34 | 
             
            #ifndef GZIP_SUPPORT
         | 
| 31 35 | 
             
            #define GZIP_SUPPORT  1
         | 
| @@ -52,7 +56,10 @@ max_uint(long n) | |
| 52 56 | 
             
            #define MAX_UINT(n) (uInt)(n)
         | 
| 53 57 | 
             
            #endif
         | 
| 54 58 |  | 
| 55 | 
            -
             | 
| 59 | 
            +
            #define OPTHASH_GIVEN_P(opts) \
         | 
| 60 | 
            +
                (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            static ID id_dictionaries, id_read, id_buffer;
         | 
| 56 63 |  | 
| 57 64 | 
             
            /*--------- Prototypes --------*/
         | 
| 58 65 |  | 
| @@ -72,6 +79,7 @@ struct zstream_run_args; | |
| 72 79 | 
             
            static void zstream_init(struct zstream*, const struct zstream_funcs*);
         | 
| 73 80 | 
             
            static void zstream_expand_buffer(struct zstream*);
         | 
| 74 81 | 
             
            static void zstream_expand_buffer_into(struct zstream*, unsigned long);
         | 
| 82 | 
            +
            static int zstream_expand_buffer_non_stream(struct zstream *z);
         | 
| 75 83 | 
             
            static void zstream_append_buffer(struct zstream*, const Bytef*, long);
         | 
| 76 84 | 
             
            static VALUE zstream_detach_buffer(struct zstream*);
         | 
| 77 85 | 
             
            static VALUE zstream_shift_buffer(struct zstream*, long);
         | 
| @@ -84,6 +92,7 @@ static void zstream_passthrough_input(struct zstream*); | |
| 84 92 | 
             
            static VALUE zstream_detach_input(struct zstream*);
         | 
| 85 93 | 
             
            static void zstream_reset(struct zstream*);
         | 
| 86 94 | 
             
            static VALUE zstream_end(struct zstream*);
         | 
| 95 | 
            +
            static VALUE zstream_ensure_end(VALUE v);
         | 
| 87 96 | 
             
            static void zstream_run(struct zstream*, Bytef*, long, int);
         | 
| 88 97 | 
             
            static VALUE zstream_sync(struct zstream*, Bytef*, long);
         | 
| 89 98 | 
             
            static void zstream_mark(void*);
         | 
| @@ -124,7 +133,7 @@ static VALUE rb_inflate_s_allocate(VALUE); | |
| 124 133 | 
             
            static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
         | 
| 125 134 | 
             
            static VALUE rb_inflate_s_inflate(VALUE, VALUE);
         | 
| 126 135 | 
             
            static void do_inflate(struct zstream*, VALUE);
         | 
| 127 | 
            -
            static VALUE rb_inflate_inflate( | 
| 136 | 
            +
            static VALUE rb_inflate_inflate(int, VALUE*, VALUE);
         | 
| 128 137 | 
             
            static VALUE rb_inflate_addstr(VALUE, VALUE);
         | 
| 129 138 | 
             
            static VALUE rb_inflate_sync(VALUE, VALUE);
         | 
| 130 139 | 
             
            static VALUE rb_inflate_sync_point_p(VALUE);
         | 
| @@ -139,19 +148,19 @@ static void gzfile_reset(struct gzfile*); | |
| 139 148 | 
             
            static void gzfile_close(struct gzfile*, int);
         | 
| 140 149 | 
             
            static void gzfile_write_raw(struct gzfile*);
         | 
| 141 150 | 
             
            static VALUE gzfile_read_raw_partial(VALUE);
         | 
| 142 | 
            -
            static VALUE gzfile_read_raw_rescue(VALUE);
         | 
| 143 | 
            -
            static VALUE gzfile_read_raw(struct gzfile | 
| 144 | 
            -
            static int gzfile_read_raw_ensure(struct gzfile*, long);
         | 
| 151 | 
            +
            static VALUE gzfile_read_raw_rescue(VALUE,VALUE);
         | 
| 152 | 
            +
            static VALUE gzfile_read_raw(struct gzfile*, VALUE outbuf);
         | 
| 153 | 
            +
            static int gzfile_read_raw_ensure(struct gzfile*, long, VALUE outbuf);
         | 
| 145 154 | 
             
            static char *gzfile_read_raw_until_zero(struct gzfile*, long);
         | 
| 146 155 | 
             
            static unsigned int gzfile_get16(const unsigned char*);
         | 
| 147 156 | 
             
            static unsigned long gzfile_get32(const unsigned char*);
         | 
| 148 157 | 
             
            static void gzfile_set32(unsigned long n, unsigned char*);
         | 
| 149 158 | 
             
            static void gzfile_make_header(struct gzfile*);
         | 
| 150 159 | 
             
            static void gzfile_make_footer(struct gzfile*);
         | 
| 151 | 
            -
            static void gzfile_read_header(struct gzfile | 
| 152 | 
            -
            static void gzfile_check_footer(struct gzfile | 
| 160 | 
            +
            static void gzfile_read_header(struct gzfile*, VALUE outbuf);
         | 
| 161 | 
            +
            static void gzfile_check_footer(struct gzfile*, VALUE outbuf);
         | 
| 153 162 | 
             
            static void gzfile_write(struct gzfile*, Bytef*, long);
         | 
| 154 | 
            -
            static long gzfile_read_more(struct gzfile | 
| 163 | 
            +
            static long gzfile_read_more(struct gzfile*, VALUE outbuf);
         | 
| 155 164 | 
             
            static void gzfile_calc_crc(struct gzfile*, VALUE);
         | 
| 156 165 | 
             
            static VALUE gzfile_read(struct gzfile*, long);
         | 
| 157 166 | 
             
            static VALUE gzfile_read_all(struct gzfile*);
         | 
| @@ -196,7 +205,7 @@ static VALUE rb_gzwriter_s_allocate(VALUE); | |
| 196 205 | 
             
            static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
         | 
| 197 206 | 
             
            static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
         | 
| 198 207 | 
             
            static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
         | 
| 199 | 
            -
            static VALUE rb_gzwriter_write( | 
| 208 | 
            +
            static VALUE rb_gzwriter_write(int, VALUE*, VALUE);
         | 
| 200 209 | 
             
            static VALUE rb_gzwriter_putc(VALUE, VALUE);
         | 
| 201 210 |  | 
| 202 211 | 
             
            static VALUE rb_gzreader_s_allocate(VALUE);
         | 
| @@ -359,11 +368,7 @@ finalizer_warn(const char *msg) | |
| 359 368 | 
             
            static VALUE
         | 
| 360 369 | 
             
            rb_zlib_version(VALUE klass)
         | 
| 361 370 | 
             
            {
         | 
| 362 | 
            -
                 | 
| 363 | 
            -
             | 
| 364 | 
            -
                str = rb_str_new2(zlibVersion());
         | 
| 365 | 
            -
                OBJ_TAINT(str);  /* for safe */
         | 
| 366 | 
            -
                return str;
         | 
| 371 | 
            +
                return rb_str_new2(zlibVersion());
         | 
| 367 372 | 
             
            }
         | 
| 368 373 |  | 
| 369 374 | 
             
            #if SIZEOF_LONG > SIZEOF_INT
         | 
| @@ -405,6 +410,15 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt)) | |
| 405 410 | 
             
                if (NIL_P(str)) {
         | 
| 406 411 | 
             
            	sum = func(sum, Z_NULL, 0);
         | 
| 407 412 | 
             
                }
         | 
| 413 | 
            +
                else if (rb_obj_is_kind_of(str, rb_cIO)) {
         | 
| 414 | 
            +
                    VALUE buf;
         | 
| 415 | 
            +
                    VALUE buflen = INT2NUM(8192);
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                    while (!NIL_P(buf = rb_funcall(str, id_read, 1, buflen))) {
         | 
| 418 | 
            +
                        StringValue(buf);
         | 
| 419 | 
            +
                        sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(buf), RSTRING_LEN(buf));
         | 
| 420 | 
            +
                    }
         | 
| 421 | 
            +
                }
         | 
| 408 422 | 
             
                else {
         | 
| 409 423 | 
             
            	StringValue(str);
         | 
| 410 424 | 
             
            	sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
         | 
| @@ -420,6 +434,8 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt)) | |
| 420 434 | 
             
             * Calculates Adler-32 checksum for +string+, and returns updated value of
         | 
| 421 435 | 
             
             * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
         | 
| 422 436 | 
             
             * +adler+ is omitted, it assumes that the initial value is given to +adler+.
         | 
| 437 | 
            +
             * If +string+ is an IO instance, reads from the IO until the IO returns nil
         | 
| 438 | 
            +
             * and returns Adler-32 of all read data.
         | 
| 423 439 | 
             
             *
         | 
| 424 440 | 
             
             * Example usage:
         | 
| 425 441 | 
             
             *
         | 
| @@ -450,7 +466,7 @@ rb_zlib_adler32(int argc, VALUE *argv, VALUE klass) | |
| 450 466 | 
             
            static VALUE
         | 
| 451 467 | 
             
            rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
         | 
| 452 468 | 
             
            {
         | 
| 453 | 
            -
             | 
| 469 | 
            +
                return ULONG2NUM(
         | 
| 454 470 | 
             
            	adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
         | 
| 455 471 | 
             
            }
         | 
| 456 472 | 
             
            #else
         | 
| @@ -464,7 +480,9 @@ rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2) | |
| 464 480 | 
             
             *
         | 
| 465 481 | 
             
             * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
         | 
| 466 482 | 
             
             * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
         | 
| 467 | 
            -
             * assumes that the initial value is given to +crc+.
         | 
| 483 | 
            +
             * assumes that the initial value is given to +crc+. If +string+ is an IO instance,
         | 
| 484 | 
            +
             * reads from the IO until the IO returns nil and returns CRC checksum of all read
         | 
| 485 | 
            +
             * data.
         | 
| 468 486 | 
             
             *
         | 
| 469 487 | 
             
             * FIXME: expression.
         | 
| 470 488 | 
             
             */
         | 
| @@ -488,7 +506,7 @@ rb_zlib_crc32(int argc, VALUE *argv, VALUE klass) | |
| 488 506 | 
             
            static VALUE
         | 
| 489 507 | 
             
            rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
         | 
| 490 508 | 
             
            {
         | 
| 491 | 
            -
             | 
| 509 | 
            +
                return ULONG2NUM(
         | 
| 492 510 | 
             
            	crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
         | 
| 493 511 | 
             
            }
         | 
| 494 512 | 
             
            #else
         | 
| @@ -527,7 +545,6 @@ rb_zlib_crc_table(VALUE obj) | |
| 527 545 | 
             
            struct zstream {
         | 
| 528 546 | 
             
                unsigned long flags;
         | 
| 529 547 | 
             
                VALUE buf;
         | 
| 530 | 
            -
                long buf_filled;
         | 
| 531 548 | 
             
                VALUE input;
         | 
| 532 549 | 
             
                z_stream stream;
         | 
| 533 550 | 
             
                const struct zstream_funcs {
         | 
| @@ -543,13 +560,17 @@ struct zstream { | |
| 543 560 | 
             
            #define ZSTREAM_FLAG_CLOSING    0x8
         | 
| 544 561 | 
             
            #define ZSTREAM_FLAG_GZFILE     0x10 /* disallows yield from expand_buffer for
         | 
| 545 562 | 
             
                                                    gzip*/
         | 
| 546 | 
            -
            #define  | 
| 563 | 
            +
            #define ZSTREAM_REUSE_BUFFER    0x20
         | 
| 564 | 
            +
            #define ZSTREAM_FLAG_UNUSED     0x40
         | 
| 547 565 |  | 
| 548 566 | 
             
            #define ZSTREAM_READY(z)       ((z)->flags |= ZSTREAM_FLAG_READY)
         | 
| 549 567 | 
             
            #define ZSTREAM_IS_READY(z)    ((z)->flags & ZSTREAM_FLAG_READY)
         | 
| 550 568 | 
             
            #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
         | 
| 551 569 | 
             
            #define ZSTREAM_IS_CLOSING(z)  ((z)->flags & ZSTREAM_FLAG_CLOSING)
         | 
| 552 570 | 
             
            #define ZSTREAM_IS_GZFILE(z)   ((z)->flags & ZSTREAM_FLAG_GZFILE)
         | 
| 571 | 
            +
            #define ZSTREAM_BUF_FILLED(z)  (NIL_P((z)->buf) ? 0 : RSTRING_LEN((z)->buf))
         | 
| 572 | 
            +
             | 
| 573 | 
            +
            #define ZSTREAM_REUSE_BUFFER_P(z)     ((z)->flags & ZSTREAM_REUSE_BUFFER)
         | 
| 553 574 |  | 
| 554 575 | 
             
            #define ZSTREAM_EXPAND_BUFFER_OK          0
         | 
| 555 576 |  | 
| @@ -599,7 +620,6 @@ zstream_init(struct zstream *z, const struct zstream_funcs *func) | |
| 599 620 | 
             
            {
         | 
| 600 621 | 
             
                z->flags = 0;
         | 
| 601 622 | 
             
                z->buf = Qnil;
         | 
| 602 | 
            -
                z->buf_filled = 0;
         | 
| 603 623 | 
             
                z->input = Qnil;
         | 
| 604 624 | 
             
                z->stream.zalloc = zlib_mem_alloc;
         | 
| 605 625 | 
             
                z->stream.zfree = zlib_mem_free;
         | 
| @@ -624,17 +644,23 @@ zstream_expand_buffer(struct zstream *z) | |
| 624 644 | 
             
                }
         | 
| 625 645 |  | 
| 626 646 | 
             
                if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
         | 
| 627 | 
            -
            	 | 
| 647 | 
            +
            	long buf_filled = ZSTREAM_BUF_FILLED(z);
         | 
| 648 | 
            +
            	if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
         | 
| 628 649 | 
             
            	    int state = 0;
         | 
| 629 | 
            -
            	    VALUE self = (VALUE)z->stream.opaque;
         | 
| 630 650 |  | 
| 631 | 
            -
             | 
| 632 | 
            -
             | 
| 633 | 
            -
             | 
| 651 | 
            +
                        if (!ZSTREAM_REUSE_BUFFER_P(z)) {
         | 
| 652 | 
            +
            	        rb_obj_reveal(z->buf, rb_cString);
         | 
| 653 | 
            +
                        }
         | 
| 634 654 |  | 
| 635 655 | 
             
            	    rb_protect(rb_yield, z->buf, &state);
         | 
| 636 656 |  | 
| 637 | 
            -
             | 
| 657 | 
            +
                        if (ZSTREAM_REUSE_BUFFER_P(z)) {
         | 
| 658 | 
            +
                            rb_str_modify(z->buf);
         | 
| 659 | 
            +
                            rb_str_set_len(z->buf, 0);
         | 
| 660 | 
            +
                        }
         | 
| 661 | 
            +
                        else {
         | 
| 662 | 
            +
                            z->buf = Qnil;
         | 
| 663 | 
            +
                        }
         | 
| 638 664 | 
             
            	    zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
         | 
| 639 665 |  | 
| 640 666 | 
             
            	    if (state)
         | 
| @@ -644,23 +670,11 @@ zstream_expand_buffer(struct zstream *z) | |
| 644 670 | 
             
            	}
         | 
| 645 671 | 
             
            	else {
         | 
| 646 672 | 
             
            	    zstream_expand_buffer_into(z,
         | 
| 647 | 
            -
             | 
| 673 | 
            +
            				       ZSTREAM_AVAIL_OUT_STEP_MAX - buf_filled);
         | 
| 648 674 | 
             
            	}
         | 
| 649 675 | 
             
                }
         | 
| 650 676 | 
             
                else {
         | 
| 651 | 
            -
            	 | 
| 652 | 
            -
            	    z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
         | 
| 653 | 
            -
            	}
         | 
| 654 | 
            -
            	else {
         | 
| 655 | 
            -
            	    long inc = z->buf_filled / 2;
         | 
| 656 | 
            -
            	    if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
         | 
| 657 | 
            -
            		inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
         | 
| 658 | 
            -
            	    }
         | 
| 659 | 
            -
            	    rb_str_resize(z->buf, z->buf_filled + inc);
         | 
| 660 | 
            -
            	    z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
         | 
| 661 | 
            -
            		(int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
         | 
| 662 | 
            -
            	}
         | 
| 663 | 
            -
            	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
         | 
| 677 | 
            +
            	zstream_expand_buffer_non_stream(z);
         | 
| 664 678 | 
             
                }
         | 
| 665 679 | 
             
            }
         | 
| 666 680 |  | 
| @@ -670,15 +684,14 @@ zstream_expand_buffer_into(struct zstream *z, unsigned long size) | |
| 670 684 | 
             
                if (NIL_P(z->buf)) {
         | 
| 671 685 | 
             
            	/* I uses rb_str_new here not rb_str_buf_new because
         | 
| 672 686 | 
             
            	   rb_str_buf_new makes a zero-length string. */
         | 
| 673 | 
            -
            	z->buf =  | 
| 674 | 
            -
            	z->buf_filled = 0;
         | 
| 687 | 
            +
            	z->buf = rb_str_buf_new(size);
         | 
| 675 688 | 
             
            	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
         | 
| 676 689 | 
             
            	z->stream.avail_out = MAX_UINT(size);
         | 
| 677 690 | 
             
            	rb_obj_hide(z->buf);
         | 
| 678 691 | 
             
                }
         | 
| 679 692 | 
             
                else if (z->stream.avail_out != size) {
         | 
| 680 | 
            -
            	 | 
| 681 | 
            -
            	z->stream.next_out = (Bytef*) | 
| 693 | 
            +
            	rb_str_modify_expand(z->buf, size);
         | 
| 694 | 
            +
            	z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
         | 
| 682 695 | 
             
            	z->stream.avail_out = MAX_UINT(size);
         | 
| 683 696 | 
             
                }
         | 
| 684 697 | 
             
            }
         | 
| @@ -695,34 +708,24 @@ zstream_expand_buffer_protect(void *ptr) | |
| 695 708 | 
             
            }
         | 
| 696 709 |  | 
| 697 710 | 
             
            static int
         | 
| 698 | 
            -
             | 
| 711 | 
            +
            zstream_expand_buffer_non_stream(struct zstream *z)
         | 
| 699 712 | 
             
            {
         | 
| 700 | 
            -
                 | 
| 701 | 
            -
                long inc, len;
         | 
| 713 | 
            +
                long inc, len = ZSTREAM_BUF_FILLED(z);
         | 
| 702 714 |  | 
| 703 | 
            -
                if ( | 
| 715 | 
            +
                if (rb_str_capacity(z->buf) - len >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
         | 
| 704 716 | 
             
            	z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
         | 
| 705 717 | 
             
                }
         | 
| 706 718 | 
             
                else {
         | 
| 707 | 
            -
            	inc =  | 
| 719 | 
            +
            	inc = len / 2;
         | 
| 708 720 | 
             
            	if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
         | 
| 709 721 | 
             
            	    inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
         | 
| 710 722 | 
             
            	}
         | 
| 711 723 |  | 
| 712 | 
            -
            	 | 
| 713 | 
            -
             | 
| 714 | 
            -
            	new_str = ruby_xrealloc(RSTRING(z->buf)->as.heap.ptr, len + 1);
         | 
| 715 | 
            -
             | 
| 716 | 
            -
            	/* from rb_str_resize */
         | 
| 717 | 
            -
            	RSTRING(z->buf)->as.heap.ptr = new_str;
         | 
| 718 | 
            -
            	RSTRING(z->buf)->as.heap.ptr[len] = '\0'; /* sentinel */
         | 
| 719 | 
            -
            	RSTRING(z->buf)->as.heap.len =
         | 
| 720 | 
            -
            	    RSTRING(z->buf)->as.heap.aux.capa = len;
         | 
| 721 | 
            -
             | 
| 724 | 
            +
            	rb_str_modify_expand(z->buf, inc);
         | 
| 722 725 | 
             
            	z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
         | 
| 723 726 | 
             
            	    (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
         | 
| 724 727 | 
             
                }
         | 
| 725 | 
            -
                z->stream.next_out = (Bytef*) | 
| 728 | 
            +
                z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
         | 
| 726 729 |  | 
| 727 730 | 
             
                return ZSTREAM_EXPAND_BUFFER_OK;
         | 
| 728 731 | 
             
            }
         | 
| @@ -733,15 +736,14 @@ zstream_append_buffer(struct zstream *z, const Bytef *src, long len) | |
| 733 736 | 
             
                if (NIL_P(z->buf)) {
         | 
| 734 737 | 
             
            	z->buf = rb_str_buf_new(len);
         | 
| 735 738 | 
             
            	rb_str_buf_cat(z->buf, (const char*)src, len);
         | 
| 736 | 
            -
            	z->buf_filled = len;
         | 
| 737 739 | 
             
            	z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
         | 
| 738 740 | 
             
            	z->stream.avail_out = 0;
         | 
| 739 741 | 
             
            	rb_obj_hide(z->buf);
         | 
| 740 742 | 
             
            	return;
         | 
| 741 743 | 
             
                }
         | 
| 742 744 |  | 
| 743 | 
            -
                if ( | 
| 744 | 
            -
            	 | 
| 745 | 
            +
                if ((long)rb_str_capacity(z->buf) < ZSTREAM_BUF_FILLED(z) + len) {
         | 
| 746 | 
            +
            	rb_str_modify_expand(z->buf, len);
         | 
| 745 747 | 
             
            	z->stream.avail_out = 0;
         | 
| 746 748 | 
             
                }
         | 
| 747 749 | 
             
                else {
         | 
| @@ -752,9 +754,8 @@ zstream_append_buffer(struct zstream *z, const Bytef *src, long len) | |
| 752 754 | 
             
            	    z->stream.avail_out = 0;
         | 
| 753 755 | 
             
            	}
         | 
| 754 756 | 
             
                }
         | 
| 755 | 
            -
                 | 
| 756 | 
            -
                z-> | 
| 757 | 
            -
                z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
         | 
| 757 | 
            +
                rb_str_cat(z->buf, (const char *)src, len);
         | 
| 758 | 
            +
                z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
         | 
| 758 759 | 
             
            }
         | 
| 759 760 |  | 
| 760 761 | 
             
            #define zstream_append_buffer2(z,v) \
         | 
| @@ -763,7 +764,7 @@ zstream_append_buffer(struct zstream *z, const Bytef *src, long len) | |
| 763 764 | 
             
            static VALUE
         | 
| 764 765 | 
             
            zstream_detach_buffer(struct zstream *z)
         | 
| 765 766 | 
             
            {
         | 
| 766 | 
            -
                VALUE dst | 
| 767 | 
            +
                VALUE dst;
         | 
| 767 768 |  | 
| 768 769 | 
             
                if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
         | 
| 769 770 | 
             
            	    rb_block_given_p()) {
         | 
| @@ -777,14 +778,12 @@ zstream_detach_buffer(struct zstream *z) | |
| 777 778 | 
             
                }
         | 
| 778 779 | 
             
                else {
         | 
| 779 780 | 
             
            	dst = z->buf;
         | 
| 780 | 
            -
             | 
| 781 | 
            -
             | 
| 781 | 
            +
                    if (!ZSTREAM_REUSE_BUFFER_P(z)) {
         | 
| 782 | 
            +
            	    rb_obj_reveal(dst, rb_cString);
         | 
| 783 | 
            +
                    }
         | 
| 782 784 | 
             
                }
         | 
| 783 785 |  | 
| 784 | 
            -
                OBJ_INFECT(dst, self);
         | 
| 785 | 
            -
             | 
| 786 786 | 
             
                z->buf = Qnil;
         | 
| 787 | 
            -
                z->buf_filled = 0;
         | 
| 788 787 | 
             
                z->stream.next_out = 0;
         | 
| 789 788 | 
             
                z->stream.avail_out = 0;
         | 
| 790 789 |  | 
| @@ -800,18 +799,20 @@ static VALUE | |
| 800 799 | 
             
            zstream_shift_buffer(struct zstream *z, long len)
         | 
| 801 800 | 
             
            {
         | 
| 802 801 | 
             
                VALUE dst;
         | 
| 803 | 
            -
                 | 
| 802 | 
            +
                char *bufptr;
         | 
| 803 | 
            +
                long buflen = ZSTREAM_BUF_FILLED(z);
         | 
| 804 804 |  | 
| 805 | 
            -
                if ( | 
| 805 | 
            +
                if (buflen <= len) {
         | 
| 806 806 | 
             
            	return zstream_detach_buffer(z);
         | 
| 807 807 | 
             
                }
         | 
| 808 808 |  | 
| 809 | 
            -
                 | 
| 810 | 
            -
                 | 
| 811 | 
            -
                 | 
| 812 | 
            -
             | 
| 813 | 
            -
                 | 
| 814 | 
            -
                 | 
| 809 | 
            +
                bufptr = RSTRING_PTR(z->buf);
         | 
| 810 | 
            +
                dst = rb_str_new(bufptr, len);
         | 
| 811 | 
            +
                buflen -= len;
         | 
| 812 | 
            +
                memmove(bufptr, bufptr + len, buflen);
         | 
| 813 | 
            +
                rb_str_set_len(z->buf, buflen);
         | 
| 814 | 
            +
                z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
         | 
| 815 | 
            +
                buflen = (long)rb_str_capacity(z->buf) - ZSTREAM_BUF_FILLED(z);
         | 
| 815 816 | 
             
                if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
         | 
| 816 817 | 
             
            	buflen = ZSTREAM_AVAIL_OUT_STEP_MAX;
         | 
| 817 818 | 
             
                }
         | 
| @@ -823,13 +824,17 @@ zstream_shift_buffer(struct zstream *z, long len) | |
| 823 824 | 
             
            static void
         | 
| 824 825 | 
             
            zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
         | 
| 825 826 | 
             
            {
         | 
| 826 | 
            -
                 | 
| 827 | 
            +
                char *bufptr;
         | 
| 828 | 
            +
                long filled;
         | 
| 829 | 
            +
             | 
| 830 | 
            +
                if (NIL_P(z->buf) || (long)rb_str_capacity(z->buf) <= ZSTREAM_BUF_FILLED(z)) {
         | 
| 827 831 | 
             
            	zstream_expand_buffer_into(z, len);
         | 
| 828 832 | 
             
                }
         | 
| 829 833 |  | 
| 830 | 
            -
                 | 
| 831 | 
            -
                memmove( | 
| 832 | 
            -
                 | 
| 834 | 
            +
                RSTRING_GETMEM(z->buf, bufptr, filled);
         | 
| 835 | 
            +
                memmove(bufptr + len, bufptr, filled);
         | 
| 836 | 
            +
                memmove(bufptr, b, len);
         | 
| 837 | 
            +
                rb_str_set_len(z->buf, filled + len);
         | 
| 833 838 | 
             
                if (z->stream.avail_out > 0) {
         | 
| 834 839 | 
             
            	if (len > z->stream.avail_out) len = z->stream.avail_out;
         | 
| 835 840 | 
             
            	z->stream.next_out+=len;
         | 
| @@ -840,17 +845,8 @@ zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len) | |
| 840 845 | 
             
            static void
         | 
| 841 846 | 
             
            zstream_buffer_ungetbyte(struct zstream *z, int c)
         | 
| 842 847 | 
             
            {
         | 
| 843 | 
            -
                 | 
| 844 | 
            -
             | 
| 845 | 
            -
                }
         | 
| 846 | 
            -
             | 
| 847 | 
            -
                memmove(RSTRING_PTR(z->buf) + 1, RSTRING_PTR(z->buf), z->buf_filled);
         | 
| 848 | 
            -
                RSTRING_PTR(z->buf)[0] = (char)c;
         | 
| 849 | 
            -
                z->buf_filled++;
         | 
| 850 | 
            -
                if (z->stream.avail_out > 0) {
         | 
| 851 | 
            -
            	z->stream.next_out++;
         | 
| 852 | 
            -
            	z->stream.avail_out--;
         | 
| 853 | 
            -
                }
         | 
| 848 | 
            +
                Bytef cc = (Bytef)c;
         | 
| 849 | 
            +
                zstream_buffer_ungets(z, &cc, 1);
         | 
| 854 850 | 
             
            }
         | 
| 855 851 |  | 
| 856 852 | 
             
            static void
         | 
| @@ -875,19 +871,50 @@ zstream_append_input(struct zstream *z, const Bytef *src, long len) | |
| 875 871 | 
             
            static void
         | 
| 876 872 | 
             
            zstream_discard_input(struct zstream *z, long len)
         | 
| 877 873 | 
             
            {
         | 
| 878 | 
            -
                if (NIL_P(z->input) | 
| 879 | 
            -
            	z->input = Qnil;
         | 
| 874 | 
            +
                if (NIL_P(z->input)) {
         | 
| 880 875 | 
             
                }
         | 
| 881 | 
            -
                else {
         | 
| 882 | 
            -
            	 | 
| 883 | 
            -
             | 
| 876 | 
            +
                else if (RBASIC_CLASS(z->input) == 0) {
         | 
| 877 | 
            +
            	/* hidden, we created z->input and have complete control */
         | 
| 878 | 
            +
            	char *ptr;
         | 
| 879 | 
            +
            	long oldlen, newlen;
         | 
| 880 | 
            +
             | 
| 881 | 
            +
            	RSTRING_GETMEM(z->input, ptr, oldlen);
         | 
| 882 | 
            +
            	newlen = oldlen - len;
         | 
| 883 | 
            +
            	if (newlen > 0) {
         | 
| 884 | 
            +
            	    memmove(ptr, ptr + len, newlen);
         | 
| 885 | 
            +
            	}
         | 
| 886 | 
            +
            	if (newlen < 0) {
         | 
| 887 | 
            +
            	    newlen = 0;
         | 
| 888 | 
            +
            	}
         | 
| 889 | 
            +
            	rb_str_resize(z->input, newlen);
         | 
| 890 | 
            +
            	if (newlen == 0) {
         | 
| 891 | 
            +
            	    rb_gc_force_recycle(z->input);
         | 
| 892 | 
            +
            	    z->input = Qnil;
         | 
| 893 | 
            +
            	}
         | 
| 894 | 
            +
            	else {
         | 
| 895 | 
            +
            	    rb_str_set_len(z->input, newlen);
         | 
| 896 | 
            +
            	}
         | 
| 897 | 
            +
                }
         | 
| 898 | 
            +
                else { /* do not mangle user-provided data */
         | 
| 899 | 
            +
            	if (RSTRING_LEN(z->input) <= len) {
         | 
| 900 | 
            +
            	    z->input = Qnil;
         | 
| 901 | 
            +
            	}
         | 
| 902 | 
            +
            	else {
         | 
| 903 | 
            +
            	    z->input = rb_str_substr(z->input, len,
         | 
| 904 | 
            +
            				     RSTRING_LEN(z->input) - len);
         | 
| 905 | 
            +
            	}
         | 
| 884 906 | 
             
                }
         | 
| 885 907 | 
             
            }
         | 
| 886 908 |  | 
| 887 909 | 
             
            static void
         | 
| 888 910 | 
             
            zstream_reset_input(struct zstream *z)
         | 
| 889 911 | 
             
            {
         | 
| 890 | 
            -
                z->input  | 
| 912 | 
            +
                if (!NIL_P(z->input) && RBASIC_CLASS(z->input) == 0) {
         | 
| 913 | 
            +
            	rb_str_resize(z->input, 0);
         | 
| 914 | 
            +
                }
         | 
| 915 | 
            +
                else {
         | 
| 916 | 
            +
            	z->input = Qnil;
         | 
| 917 | 
            +
                }
         | 
| 891 918 | 
             
            }
         | 
| 892 919 |  | 
| 893 920 | 
             
            static void
         | 
| @@ -912,7 +939,6 @@ zstream_detach_input(struct zstream *z) | |
| 912 939 | 
             
            	rb_obj_reveal(dst, rb_cString);
         | 
| 913 940 | 
             
                }
         | 
| 914 941 | 
             
                z->input = Qnil;
         | 
| 915 | 
            -
                rb_obj_reveal(dst, rb_cString);
         | 
| 916 942 | 
             
                return dst;
         | 
| 917 943 | 
             
            }
         | 
| 918 944 |  | 
| @@ -927,7 +953,6 @@ zstream_reset(struct zstream *z) | |
| 927 953 | 
             
                }
         | 
| 928 954 | 
             
                z->flags = ZSTREAM_FLAG_READY;
         | 
| 929 955 | 
             
                z->buf = Qnil;
         | 
| 930 | 
            -
                z->buf_filled = 0;
         | 
| 931 956 | 
             
                z->stream.next_out = 0;
         | 
| 932 957 | 
             
                z->stream.avail_out = 0;
         | 
| 933 958 | 
             
                zstream_reset_input(z);
         | 
| @@ -956,6 +981,12 @@ zstream_end(struct zstream *z) | |
| 956 981 | 
             
                return Qnil;
         | 
| 957 982 | 
             
            }
         | 
| 958 983 |  | 
| 984 | 
            +
            static VALUE
         | 
| 985 | 
            +
            zstream_ensure_end(VALUE v)
         | 
| 986 | 
            +
            {
         | 
| 987 | 
            +
                return zstream_end((struct zstream *)v);
         | 
| 988 | 
            +
            }
         | 
| 989 | 
            +
             | 
| 959 990 | 
             
            static void *
         | 
| 960 991 | 
             
            zstream_run_func(void *ptr)
         | 
| 961 992 | 
             
            {
         | 
| @@ -968,7 +999,7 @@ zstream_run_func(void *ptr) | |
| 968 999 | 
             
                while (!args->interrupt) {
         | 
| 969 1000 | 
             
            	n = z->stream.avail_out;
         | 
| 970 1001 | 
             
            	err = z->func->run(&z->stream, flush);
         | 
| 971 | 
            -
            	z-> | 
| 1002 | 
            +
            	rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
         | 
| 972 1003 |  | 
| 973 1004 | 
             
            	if (err == Z_STREAM_END) {
         | 
| 974 1005 | 
             
            	    z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
         | 
| @@ -997,7 +1028,7 @@ zstream_run_func(void *ptr) | |
| 997 1028 | 
             
            							(void *)z);
         | 
| 998 1029 | 
             
            	}
         | 
| 999 1030 | 
             
            	else {
         | 
| 1000 | 
            -
            	    state =  | 
| 1031 | 
            +
            	    state = zstream_expand_buffer_non_stream(z);
         | 
| 1001 1032 | 
             
            	}
         | 
| 1002 1033 |  | 
| 1003 1034 | 
             
            	if (state) {
         | 
| @@ -1012,6 +1043,7 @@ zstream_run_func(void *ptr) | |
| 1012 1043 |  | 
| 1013 1044 | 
             
            /*
         | 
| 1014 1045 | 
             
             * There is no safe way to interrupt z->run->func().
         | 
| 1046 | 
            +
             * async-signal-safe
         | 
| 1015 1047 | 
             
             */
         | 
| 1016 1048 | 
             
            static void
         | 
| 1017 1049 | 
             
            zstream_unblock_func(void *ptr)
         | 
| @@ -1026,7 +1058,7 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush) | |
| 1026 1058 | 
             
            {
         | 
| 1027 1059 | 
             
                struct zstream_run_args args;
         | 
| 1028 1060 | 
             
                int err;
         | 
| 1029 | 
            -
                VALUE  | 
| 1061 | 
            +
                VALUE old_input = Qnil;
         | 
| 1030 1062 |  | 
| 1031 1063 | 
             
                args.z = z;
         | 
| 1032 1064 | 
             
                args.flush = flush;
         | 
| @@ -1040,12 +1072,13 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush) | |
| 1040 1072 | 
             
                }
         | 
| 1041 1073 | 
             
                else {
         | 
| 1042 1074 | 
             
            	zstream_append_input(z, src, len);
         | 
| 1043 | 
            -
            	z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
         | 
| 1044 | 
            -
            	z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
         | 
| 1045 1075 | 
             
            	/* keep reference to `z->input' so as not to be garbage collected
         | 
| 1046 1076 | 
             
            	   after zstream_reset_input() and prevent `z->stream.next_in'
         | 
| 1047 1077 | 
             
            	   from dangling. */
         | 
| 1048 | 
            -
            	 | 
| 1078 | 
            +
            	old_input = zstream_detach_input(z);
         | 
| 1079 | 
            +
            	rb_obj_hide(old_input); /* for GVL release and later recycle */
         | 
| 1080 | 
            +
            	z->stream.next_in = (Bytef*)RSTRING_PTR(old_input);
         | 
| 1081 | 
            +
            	z->stream.avail_in = MAX_UINT(RSTRING_LEN(old_input));
         | 
| 1049 1082 | 
             
                }
         | 
| 1050 1083 |  | 
| 1051 1084 | 
             
                if (z->stream.avail_out == 0) {
         | 
| @@ -1053,8 +1086,14 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush) | |
| 1053 1086 | 
             
                }
         | 
| 1054 1087 |  | 
| 1055 1088 | 
             
            loop:
         | 
| 1089 | 
            +
            #ifndef RB_NOGVL_UBF_ASYNC_SAFE
         | 
| 1056 1090 | 
             
                err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
         | 
| 1057 1091 | 
             
            						 zstream_unblock_func, (void *)&args);
         | 
| 1092 | 
            +
            #else
         | 
| 1093 | 
            +
                err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
         | 
| 1094 | 
            +
                                           zstream_unblock_func, (void *)&args,
         | 
| 1095 | 
            +
                                           RB_NOGVL_UBF_ASYNC_SAFE);
         | 
| 1096 | 
            +
            #endif
         | 
| 1058 1097 |  | 
| 1059 1098 | 
             
                if (flush != Z_FINISH && err == Z_BUF_ERROR
         | 
| 1060 1099 | 
             
            	    && z->stream.avail_out > 0) {
         | 
| @@ -1083,7 +1122,10 @@ loop: | |
| 1083 1122 |  | 
| 1084 1123 | 
             
                if (z->stream.avail_in > 0) {
         | 
| 1085 1124 | 
             
            	zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
         | 
| 1086 | 
            -
             | 
| 1125 | 
            +
                }
         | 
| 1126 | 
            +
                if (!NIL_P(old_input)) {
         | 
| 1127 | 
            +
            	rb_str_resize(old_input, 0);
         | 
| 1128 | 
            +
            	rb_gc_force_recycle(old_input);
         | 
| 1087 1129 | 
             
                }
         | 
| 1088 1130 |  | 
| 1089 1131 | 
             
                if (args.jump_state)
         | 
| @@ -1316,7 +1358,6 @@ rb_zstream_flush_next_in(VALUE obj) | |
| 1316 1358 |  | 
| 1317 1359 | 
             
                TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
         | 
| 1318 1360 | 
             
                dst = zstream_detach_input(z);
         | 
| 1319 | 
            -
                OBJ_INFECT(dst, obj);
         | 
| 1320 1361 | 
             
                return dst;
         | 
| 1321 1362 | 
             
            }
         | 
| 1322 1363 |  | 
| @@ -1412,7 +1453,7 @@ rb_zstream_data_type(VALUE obj) | |
| 1412 1453 | 
             
            static VALUE
         | 
| 1413 1454 | 
             
            rb_zstream_adler(VALUE obj)
         | 
| 1414 1455 | 
             
            {
         | 
| 1415 | 
            -
             | 
| 1456 | 
            +
                return rb_uint2inum(get_zstream(obj)->stream.adler);
         | 
| 1416 1457 | 
             
            }
         | 
| 1417 1458 |  | 
| 1418 1459 | 
             
            /*
         | 
| @@ -1577,7 +1618,6 @@ rb_deflate_init_copy(VALUE self, VALUE orig) | |
| 1577 1618 | 
             
                }
         | 
| 1578 1619 | 
             
                z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
         | 
| 1579 1620 | 
             
                z1->buf   = NIL_P(z2->buf)   ? Qnil : rb_str_dup(z2->buf);
         | 
| 1580 | 
            -
                z1->buf_filled = z2->buf_filled;
         | 
| 1581 1621 | 
             
                z1->flags = z2->flags;
         | 
| 1582 1622 |  | 
| 1583 1623 | 
             
                return self;
         | 
| @@ -1636,9 +1676,8 @@ rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass) | |
| 1636 1676 |  | 
| 1637 1677 | 
             
                args[0] = (VALUE)&z;
         | 
| 1638 1678 | 
             
                args[1] = src;
         | 
| 1639 | 
            -
                dst = rb_ensure(deflate_run, (VALUE)args,  | 
| 1679 | 
            +
                dst = rb_ensure(deflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
         | 
| 1640 1680 |  | 
| 1641 | 
            -
                OBJ_INFECT(dst, src);
         | 
| 1642 1681 | 
             
                return dst;
         | 
| 1643 1682 | 
             
            }
         | 
| 1644 1683 |  | 
| @@ -1688,7 +1727,6 @@ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj) | |
| 1688 1727 | 
             
                VALUE src, flush;
         | 
| 1689 1728 |  | 
| 1690 1729 | 
             
                rb_scan_args(argc, argv, "11", &src, &flush);
         | 
| 1691 | 
            -
                OBJ_INFECT(obj, src);
         | 
| 1692 1730 | 
             
                do_deflate(z, src, ARG_FLUSH(flush));
         | 
| 1693 1731 |  | 
| 1694 1732 | 
             
                return zstream_detach_buffer(z);
         | 
| @@ -1706,7 +1744,6 @@ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj) | |
| 1706 1744 | 
             
            static VALUE
         | 
| 1707 1745 | 
             
            rb_deflate_addstr(VALUE obj, VALUE src)
         | 
| 1708 1746 | 
             
            {
         | 
| 1709 | 
            -
                OBJ_INFECT(obj, src);
         | 
| 1710 1747 | 
             
                do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
         | 
| 1711 1748 | 
             
                return obj;
         | 
| 1712 1749 | 
             
            }
         | 
| @@ -1761,23 +1798,26 @@ rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy) | |
| 1761 1798 | 
             
                int level, strategy;
         | 
| 1762 1799 | 
             
                int err;
         | 
| 1763 1800 | 
             
                uInt n;
         | 
| 1801 | 
            +
                long filled;
         | 
| 1764 1802 |  | 
| 1765 1803 | 
             
                level = ARG_LEVEL(v_level);
         | 
| 1766 1804 | 
             
                strategy = ARG_STRATEGY(v_strategy);
         | 
| 1767 1805 |  | 
| 1768 1806 | 
             
                n = z->stream.avail_out;
         | 
| 1769 1807 | 
             
                err = deflateParams(&z->stream, level, strategy);
         | 
| 1770 | 
            -
                 | 
| 1808 | 
            +
                filled = n - z->stream.avail_out;
         | 
| 1771 1809 | 
             
                while (err == Z_BUF_ERROR) {
         | 
| 1772 1810 | 
             
            	rb_warning("deflateParams() returned Z_BUF_ERROR");
         | 
| 1773 1811 | 
             
            	zstream_expand_buffer(z);
         | 
| 1812 | 
            +
            	rb_str_set_len(z->buf, RSTRING_LEN(z->buf) + filled);
         | 
| 1774 1813 | 
             
            	n = z->stream.avail_out;
         | 
| 1775 1814 | 
             
            	err = deflateParams(&z->stream, level, strategy);
         | 
| 1776 | 
            -
            	 | 
| 1815 | 
            +
            	filled = n - z->stream.avail_out;
         | 
| 1777 1816 | 
             
                }
         | 
| 1778 1817 | 
             
                if (err != Z_OK) {
         | 
| 1779 1818 | 
             
            	raise_zlib_error(err, z->stream.msg);
         | 
| 1780 1819 | 
             
                }
         | 
| 1820 | 
            +
                rb_str_set_len(z->buf, RSTRING_LEN(z->buf) + filled);
         | 
| 1781 1821 |  | 
| 1782 1822 | 
             
                return Qnil;
         | 
| 1783 1823 | 
             
            }
         | 
| @@ -1803,7 +1843,6 @@ rb_deflate_set_dictionary(VALUE obj, VALUE dic) | |
| 1803 1843 | 
             
                VALUE src = dic;
         | 
| 1804 1844 | 
             
                int err;
         | 
| 1805 1845 |  | 
| 1806 | 
            -
                OBJ_INFECT(obj, dic);
         | 
| 1807 1846 | 
             
                StringValue(src);
         | 
| 1808 1847 | 
             
                err = deflateSetDictionary(&z->stream,
         | 
| 1809 1848 | 
             
            			       (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
         | 
| @@ -1948,9 +1987,8 @@ rb_inflate_s_inflate(VALUE obj, VALUE src) | |
| 1948 1987 |  | 
| 1949 1988 | 
             
                args[0] = (VALUE)&z;
         | 
| 1950 1989 | 
             
                args[1] = src;
         | 
| 1951 | 
            -
                dst = rb_ensure(inflate_run, (VALUE)args,  | 
| 1990 | 
            +
                dst = rb_ensure(inflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
         | 
| 1952 1991 |  | 
| 1953 | 
            -
                OBJ_INFECT(dst, src);
         | 
| 1954 1992 | 
             
                return dst;
         | 
| 1955 1993 | 
             
            }
         | 
| 1956 1994 |  | 
| @@ -1991,8 +2029,8 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) | |
| 1991 2029 | 
             
             * Document-method: Zlib::Inflate#inflate
         | 
| 1992 2030 | 
             
             *
         | 
| 1993 2031 | 
             
             * call-seq:
         | 
| 1994 | 
            -
             *   inflate(deflate_string)                 -> String
         | 
| 1995 | 
            -
             *   inflate(deflate_string) { |chunk| ... } -> nil
         | 
| 2032 | 
            +
             *   inflate(deflate_string, buffer: nil)                 -> String
         | 
| 2033 | 
            +
             *   inflate(deflate_string, buffer: nil) { |chunk| ... } -> nil
         | 
| 1996 2034 | 
             
             *
         | 
| 1997 2035 | 
             
             * Inputs +deflate_string+ into the inflate stream and returns the output from
         | 
| 1998 2036 | 
             
             * the stream.  Calling this method, both the input and the output buffer of
         | 
| @@ -2002,6 +2040,15 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) | |
| 2002 2040 | 
             
             * If a block is given consecutive inflated chunks from the +deflate_string+
         | 
| 2003 2041 | 
             
             * are yielded to the block and +nil+ is returned.
         | 
| 2004 2042 | 
             
             *
         | 
| 2043 | 
            +
             * If a :buffer keyword argument is given and not nil:
         | 
| 2044 | 
            +
             *
         | 
| 2045 | 
            +
             * * The :buffer keyword should be a String, and will used as the output buffer.
         | 
| 2046 | 
            +
             *   Using this option can reuse the memory required during inflation.
         | 
| 2047 | 
            +
             * * When not passing a block, the return value will be the same object as the
         | 
| 2048 | 
            +
             *   :buffer keyword argument.
         | 
| 2049 | 
            +
             * * When passing a block, the yielded chunks will be the same value as the
         | 
| 2050 | 
            +
             *   :buffer keyword argument.
         | 
| 2051 | 
            +
             *
         | 
| 2005 2052 | 
             
             * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
         | 
| 2006 2053 | 
             
             * decompress.  Set the dictionary by Zlib::Inflate#set_dictionary and then
         | 
| 2007 2054 | 
             
             * call this method again with an empty string to flush the stream:
         | 
| @@ -2025,12 +2072,37 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) | |
| 2025 2072 | 
             
             * See also Zlib::Inflate.new
         | 
| 2026 2073 | 
             
             */
         | 
| 2027 2074 | 
             
            static VALUE
         | 
| 2028 | 
            -
            rb_inflate_inflate(VALUE  | 
| 2075 | 
            +
            rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
         | 
| 2029 2076 | 
             
            {
         | 
| 2030 2077 | 
             
                struct zstream *z = get_zstream(obj);
         | 
| 2031 | 
            -
                VALUE dst;
         | 
| 2078 | 
            +
                VALUE dst, src, opts, buffer = Qnil;
         | 
| 2032 2079 |  | 
| 2033 | 
            -
                 | 
| 2080 | 
            +
                if (OPTHASH_GIVEN_P(opts)) {
         | 
| 2081 | 
            +
                    VALUE buf;
         | 
| 2082 | 
            +
                    rb_get_kwargs(opts, &id_buffer, 0, 1, &buf);
         | 
| 2083 | 
            +
                    if (buf != Qundef && buf != Qnil) {
         | 
| 2084 | 
            +
                        buffer = StringValue(buf);
         | 
| 2085 | 
            +
                    }
         | 
| 2086 | 
            +
                }
         | 
| 2087 | 
            +
                if (buffer != Qnil) {
         | 
| 2088 | 
            +
                    if (!(ZSTREAM_REUSE_BUFFER_P(z) && z->buf == buffer)) {
         | 
| 2089 | 
            +
                        long len = RSTRING_LEN(buffer);
         | 
| 2090 | 
            +
                        if (len >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
         | 
| 2091 | 
            +
                            rb_str_modify(buffer);
         | 
| 2092 | 
            +
                        }
         | 
| 2093 | 
            +
                        else {
         | 
| 2094 | 
            +
                            len = ZSTREAM_AVAIL_OUT_STEP_MAX - len;
         | 
| 2095 | 
            +
                            rb_str_modify_expand(buffer, len);
         | 
| 2096 | 
            +
                        }
         | 
| 2097 | 
            +
                        rb_str_set_len(buffer, 0);
         | 
| 2098 | 
            +
                        z->flags |= ZSTREAM_REUSE_BUFFER;
         | 
| 2099 | 
            +
                        z->buf = buffer;
         | 
| 2100 | 
            +
                    }
         | 
| 2101 | 
            +
                } else if (ZSTREAM_REUSE_BUFFER_P(z)) {
         | 
| 2102 | 
            +
                    z->flags &= ~ZSTREAM_REUSE_BUFFER;
         | 
| 2103 | 
            +
                    z->buf = Qnil;
         | 
| 2104 | 
            +
                }
         | 
| 2105 | 
            +
                rb_scan_args(argc, argv, "10", &src);
         | 
| 2034 2106 |  | 
| 2035 2107 | 
             
                if (ZSTREAM_IS_FINISHED(z)) {
         | 
| 2036 2108 | 
             
            	if (NIL_P(src)) {
         | 
| @@ -2039,8 +2111,11 @@ rb_inflate_inflate(VALUE obj, VALUE src) | |
| 2039 2111 | 
             
            	else {
         | 
| 2040 2112 | 
             
            	    StringValue(src);
         | 
| 2041 2113 | 
             
            	    zstream_append_buffer2(z, src);
         | 
| 2042 | 
            -
            	     | 
| 2043 | 
            -
             | 
| 2114 | 
            +
            	    if (ZSTREAM_REUSE_BUFFER_P(z)) {
         | 
| 2115 | 
            +
                            dst = rb_str_resize(buffer, 0);
         | 
| 2116 | 
            +
                        } else {
         | 
| 2117 | 
            +
                            dst = rb_str_new(0, 0);
         | 
| 2118 | 
            +
                        }
         | 
| 2044 2119 | 
             
            	}
         | 
| 2045 2120 | 
             
                }
         | 
| 2046 2121 | 
             
                else {
         | 
| @@ -2066,8 +2141,6 @@ rb_inflate_addstr(VALUE obj, VALUE src) | |
| 2066 2141 | 
             
            {
         | 
| 2067 2142 | 
             
                struct zstream *z = get_zstream(obj);
         | 
| 2068 2143 |  | 
| 2069 | 
            -
                OBJ_INFECT(obj, src);
         | 
| 2070 | 
            -
             | 
| 2071 2144 | 
             
                if (ZSTREAM_IS_FINISHED(z)) {
         | 
| 2072 2145 | 
             
            	if (!NIL_P(src)) {
         | 
| 2073 2146 | 
             
            	    StringValue(src);
         | 
| @@ -2097,7 +2170,6 @@ rb_inflate_sync(VALUE obj, VALUE src) | |
| 2097 2170 | 
             
            {
         | 
| 2098 2171 | 
             
                struct zstream *z = get_zstream(obj);
         | 
| 2099 2172 |  | 
| 2100 | 
            -
                OBJ_INFECT(obj, src);
         | 
| 2101 2173 | 
             
                StringValue(src);
         | 
| 2102 2174 | 
             
                return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
         | 
| 2103 2175 | 
             
            }
         | 
| @@ -2139,7 +2211,6 @@ rb_inflate_set_dictionary(VALUE obj, VALUE dic) | |
| 2139 2211 | 
             
                VALUE src = dic;
         | 
| 2140 2212 | 
             
                int err;
         | 
| 2141 2213 |  | 
| 2142 | 
            -
                OBJ_INFECT(obj, dic);
         | 
| 2143 2214 | 
             
                StringValue(src);
         | 
| 2144 2215 | 
             
                err = inflateSetDictionary(&z->stream,
         | 
| 2145 2216 | 
             
            			       (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
         | 
| @@ -2196,7 +2267,7 @@ rb_inflate_set_dictionary(VALUE obj, VALUE dic) | |
| 2196 2267 | 
             
            #define OS_CODE  OS_UNIX
         | 
| 2197 2268 | 
             
            #endif
         | 
| 2198 2269 |  | 
| 2199 | 
            -
            static ID id_write,  | 
| 2270 | 
            +
            static ID id_write, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
         | 
| 2200 2271 | 
             
            static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
         | 
| 2201 2272 |  | 
| 2202 2273 |  | 
| @@ -2220,7 +2291,6 @@ struct gzfile { | |
| 2220 2291 | 
             
                rb_encoding *enc2;
         | 
| 2221 2292 | 
             
                rb_econv_t *ec;
         | 
| 2222 2293 | 
             
                VALUE ecopts;
         | 
| 2223 | 
            -
                char *cbuf;
         | 
| 2224 2294 | 
             
                VALUE path;
         | 
| 2225 2295 | 
             
            };
         | 
| 2226 2296 | 
             
            #define GZFILE_CBUF_CAPA 10
         | 
| @@ -2228,12 +2298,23 @@ struct gzfile { | |
| 2228 2298 | 
             
            #define GZFILE_FLAG_SYNC             ZSTREAM_FLAG_UNUSED
         | 
| 2229 2299 | 
             
            #define GZFILE_FLAG_HEADER_FINISHED  (ZSTREAM_FLAG_UNUSED << 1)
         | 
| 2230 2300 | 
             
            #define GZFILE_FLAG_FOOTER_FINISHED  (ZSTREAM_FLAG_UNUSED << 2)
         | 
| 2301 | 
            +
            #define GZFILE_FLAG_MTIME_IS_SET     (ZSTREAM_FLAG_UNUSED << 3)
         | 
| 2231 2302 |  | 
| 2232 2303 | 
             
            #define GZFILE_IS_FINISHED(gz) \
         | 
| 2233 | 
            -
                (ZSTREAM_IS_FINISHED(&(gz)->z) && (gz)->z | 
| 2304 | 
            +
                (ZSTREAM_IS_FINISHED(&(gz)->z) && ZSTREAM_BUF_FILLED(&(gz)->z) == 0)
         | 
| 2234 2305 |  | 
| 2235 2306 | 
             
            #define GZFILE_READ_SIZE  2048
         | 
| 2236 2307 |  | 
| 2308 | 
            +
            struct read_raw_arg {
         | 
| 2309 | 
            +
                VALUE io;
         | 
| 2310 | 
            +
                union {
         | 
| 2311 | 
            +
            	const VALUE argv[2]; /* for rb_funcallv */
         | 
| 2312 | 
            +
            	struct {
         | 
| 2313 | 
            +
            	    VALUE len;
         | 
| 2314 | 
            +
            	    VALUE buf;
         | 
| 2315 | 
            +
            	} in;
         | 
| 2316 | 
            +
                } as;
         | 
| 2317 | 
            +
            };
         | 
| 2237 2318 |  | 
| 2238 2319 | 
             
            static void
         | 
| 2239 2320 | 
             
            gzfile_mark(void *p)
         | 
| @@ -2260,22 +2341,13 @@ gzfile_free(void *p) | |
| 2260 2341 | 
             
            	}
         | 
| 2261 2342 | 
             
            	zstream_finalize(z);
         | 
| 2262 2343 | 
             
                }
         | 
| 2263 | 
            -
                if (gz->cbuf) {
         | 
| 2264 | 
            -
            	xfree(gz->cbuf);
         | 
| 2265 | 
            -
                }
         | 
| 2266 2344 | 
             
                xfree(gz);
         | 
| 2267 2345 | 
             
            }
         | 
| 2268 2346 |  | 
| 2269 2347 | 
             
            static size_t
         | 
| 2270 2348 | 
             
            gzfile_memsize(const void *p)
         | 
| 2271 2349 | 
             
            {
         | 
| 2272 | 
            -
                 | 
| 2273 | 
            -
                size_t size = sizeof(struct gzfile);
         | 
| 2274 | 
            -
             | 
| 2275 | 
            -
                if (gz->cbuf)
         | 
| 2276 | 
            -
            	size += GZFILE_CBUF_CAPA;
         | 
| 2277 | 
            -
             | 
| 2278 | 
            -
                return size;
         | 
| 2350 | 
            +
                return sizeof(struct gzfile);
         | 
| 2279 2351 | 
             
            }
         | 
| 2280 2352 |  | 
| 2281 2353 | 
             
            static const rb_data_type_t gzfile_data_type = {
         | 
| @@ -2304,7 +2376,6 @@ gzfile_init(struct gzfile *gz, const struct zstream_funcs *funcs, void (*endfunc | |
| 2304 2376 | 
             
                gz->ec = NULL;
         | 
| 2305 2377 | 
             
                gz->ecflags = 0;
         | 
| 2306 2378 | 
             
                gz->ecopts = Qnil;
         | 
| 2307 | 
            -
                gz->cbuf = 0;
         | 
| 2308 2379 | 
             
                gz->path = Qnil;
         | 
| 2309 2380 | 
             
            }
         | 
| 2310 2381 |  | 
| @@ -2356,9 +2427,8 @@ gzfile_write_raw(struct gzfile *gz) | |
| 2356 2427 | 
             
            {
         | 
| 2357 2428 | 
             
                VALUE str;
         | 
| 2358 2429 |  | 
| 2359 | 
            -
                if (gz->z | 
| 2430 | 
            +
                if (ZSTREAM_BUF_FILLED(&gz->z) > 0) {
         | 
| 2360 2431 | 
             
            	str = zstream_detach_buffer(&gz->z);
         | 
| 2361 | 
            -
            	OBJ_TAINT(str);  /* for safe */
         | 
| 2362 2432 | 
             
            	rb_funcall(gz->io, id_write, 1, str);
         | 
| 2363 2433 | 
             
            	if ((gz->z.flags & GZFILE_FLAG_SYNC)
         | 
| 2364 2434 | 
             
            	    && rb_respond_to(gz->io, id_flush))
         | 
| @@ -2369,21 +2439,23 @@ gzfile_write_raw(struct gzfile *gz) | |
| 2369 2439 | 
             
            static VALUE
         | 
| 2370 2440 | 
             
            gzfile_read_raw_partial(VALUE arg)
         | 
| 2371 2441 | 
             
            {
         | 
| 2372 | 
            -
                struct  | 
| 2442 | 
            +
                struct read_raw_arg *ra = (struct read_raw_arg *)arg;
         | 
| 2373 2443 | 
             
                VALUE str;
         | 
| 2444 | 
            +
                int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
         | 
| 2374 2445 |  | 
| 2375 | 
            -
                str =  | 
| 2446 | 
            +
                str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv);
         | 
| 2376 2447 | 
             
                Check_Type(str, T_STRING);
         | 
| 2377 2448 | 
             
                return str;
         | 
| 2378 2449 | 
             
            }
         | 
| 2379 2450 |  | 
| 2380 2451 | 
             
            static VALUE
         | 
| 2381 | 
            -
            gzfile_read_raw_rescue(VALUE arg)
         | 
| 2452 | 
            +
            gzfile_read_raw_rescue(VALUE arg, VALUE _)
         | 
| 2382 2453 | 
             
            {
         | 
| 2383 | 
            -
                struct  | 
| 2454 | 
            +
                struct read_raw_arg *ra = (struct read_raw_arg *)arg;
         | 
| 2384 2455 | 
             
                VALUE str = Qnil;
         | 
| 2385 2456 | 
             
                if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
         | 
| 2386 | 
            -
             | 
| 2457 | 
            +
            	int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
         | 
| 2458 | 
            +
            	str = rb_funcallv(ra->io, id_read, argc, ra->as.argv);
         | 
| 2387 2459 | 
             
                    if (!NIL_P(str)) {
         | 
| 2388 2460 | 
             
                        Check_Type(str, T_STRING);
         | 
| 2389 2461 | 
             
                    }
         | 
| @@ -2392,15 +2464,21 @@ gzfile_read_raw_rescue(VALUE arg) | |
| 2392 2464 | 
             
            }
         | 
| 2393 2465 |  | 
| 2394 2466 | 
             
            static VALUE
         | 
| 2395 | 
            -
            gzfile_read_raw(struct gzfile *gz)
         | 
| 2467 | 
            +
            gzfile_read_raw(struct gzfile *gz, VALUE outbuf)
         | 
| 2396 2468 | 
             
            {
         | 
| 2397 | 
            -
                 | 
| 2398 | 
            -
             | 
| 2469 | 
            +
                struct read_raw_arg ra;
         | 
| 2470 | 
            +
             | 
| 2471 | 
            +
                ra.io = gz->io;
         | 
| 2472 | 
            +
                ra.as.in.len = INT2FIX(GZFILE_READ_SIZE);
         | 
| 2473 | 
            +
                ra.as.in.buf = outbuf;
         | 
| 2474 | 
            +
             | 
| 2475 | 
            +
                return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
         | 
| 2476 | 
            +
                                  gzfile_read_raw_rescue, (VALUE)&ra,
         | 
| 2399 2477 | 
             
                                  rb_eEOFError, rb_eNoMethodError, (VALUE)0);
         | 
| 2400 2478 | 
             
            }
         | 
| 2401 2479 |  | 
| 2402 2480 | 
             
            static int
         | 
| 2403 | 
            -
            gzfile_read_raw_ensure(struct gzfile *gz, long size)
         | 
| 2481 | 
            +
            gzfile_read_raw_ensure(struct gzfile *gz, long size, VALUE outbuf)
         | 
| 2404 2482 | 
             
            {
         | 
| 2405 2483 | 
             
                VALUE str;
         | 
| 2406 2484 |  | 
| @@ -2409,7 +2487,7 @@ gzfile_read_raw_ensure(struct gzfile *gz, long size) | |
| 2409 2487 | 
             
            	    rb_raise(cGzError, "unexpected end of string");
         | 
| 2410 2488 | 
             
                }
         | 
| 2411 2489 | 
             
                while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
         | 
| 2412 | 
            -
            	str = gzfile_read_raw(gz);
         | 
| 2490 | 
            +
            	str = gzfile_read_raw(gz, outbuf);
         | 
| 2413 2491 | 
             
            	if (NIL_P(str)) return 0;
         | 
| 2414 2492 | 
             
            	zstream_append_input2(&gz->z, str);
         | 
| 2415 2493 | 
             
                }
         | 
| @@ -2426,7 +2504,7 @@ gzfile_read_raw_until_zero(struct gzfile *gz, long offset) | |
| 2426 2504 | 
             
            	p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
         | 
| 2427 2505 | 
             
            		   RSTRING_LEN(gz->z.input) - offset);
         | 
| 2428 2506 | 
             
            	if (p) break;
         | 
| 2429 | 
            -
            	str = gzfile_read_raw(gz);
         | 
| 2507 | 
            +
            	str = gzfile_read_raw(gz, Qnil);
         | 
| 2430 2508 | 
             
            	if (NIL_P(str)) {
         | 
| 2431 2509 | 
             
            	    rb_raise(cGzError, "unexpected end of file");
         | 
| 2432 2510 | 
             
            	}
         | 
| @@ -2507,7 +2585,7 @@ gzfile_make_header(struct gzfile *gz) | |
| 2507 2585 | 
             
                if (!NIL_P(gz->comment)) {
         | 
| 2508 2586 | 
             
            	flags |= GZ_FLAG_COMMENT;
         | 
| 2509 2587 | 
             
                }
         | 
| 2510 | 
            -
                if (gz-> | 
| 2588 | 
            +
                if (!(gz->z.flags & GZFILE_FLAG_MTIME_IS_SET)) {
         | 
| 2511 2589 | 
             
            	gz->mtime = time(0);
         | 
| 2512 2590 | 
             
                }
         | 
| 2513 2591 |  | 
| @@ -2551,13 +2629,14 @@ gzfile_make_footer(struct gzfile *gz) | |
| 2551 2629 | 
             
            }
         | 
| 2552 2630 |  | 
| 2553 2631 | 
             
            static void
         | 
| 2554 | 
            -
            gzfile_read_header(struct gzfile *gz)
         | 
| 2632 | 
            +
            gzfile_read_header(struct gzfile *gz, VALUE outbuf)
         | 
| 2555 2633 | 
             
            {
         | 
| 2556 2634 | 
             
                const unsigned char *head;
         | 
| 2557 2635 | 
             
                long len;
         | 
| 2558 2636 | 
             
                char flags, *p;
         | 
| 2559 2637 |  | 
| 2560 | 
            -
                 | 
| 2638 | 
            +
                /* 10 is the size of gzip header */
         | 
| 2639 | 
            +
                if (!gzfile_read_raw_ensure(gz, 10, outbuf)) {
         | 
| 2561 2640 | 
             
            	gzfile_raise(gz, cGzError, "not in gzip format");
         | 
| 2562 2641 | 
             
                }
         | 
| 2563 2642 |  | 
| @@ -2596,33 +2675,31 @@ gzfile_read_header(struct gzfile *gz) | |
| 2596 2675 | 
             
                zstream_discard_input(&gz->z, 10);
         | 
| 2597 2676 |  | 
| 2598 2677 | 
             
                if (flags & GZ_FLAG_EXTRA) {
         | 
| 2599 | 
            -
            	if (!gzfile_read_raw_ensure(gz, 2)) {
         | 
| 2678 | 
            +
            	if (!gzfile_read_raw_ensure(gz, 2, outbuf)) {
         | 
| 2600 2679 | 
             
            	    rb_raise(cGzError, "unexpected end of file");
         | 
| 2601 2680 | 
             
            	}
         | 
| 2602 2681 | 
             
            	len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
         | 
| 2603 | 
            -
            	if (!gzfile_read_raw_ensure(gz, 2 + len)) {
         | 
| 2682 | 
            +
            	if (!gzfile_read_raw_ensure(gz, 2 + len, outbuf)) {
         | 
| 2604 2683 | 
             
            	    rb_raise(cGzError, "unexpected end of file");
         | 
| 2605 2684 | 
             
            	}
         | 
| 2606 2685 | 
             
            	zstream_discard_input(&gz->z, 2 + len);
         | 
| 2607 2686 | 
             
                }
         | 
| 2608 2687 | 
             
                if (flags & GZ_FLAG_ORIG_NAME) {
         | 
| 2609 | 
            -
            	if (!gzfile_read_raw_ensure(gz, 1)) {
         | 
| 2688 | 
            +
            	if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
         | 
| 2610 2689 | 
             
            	    rb_raise(cGzError, "unexpected end of file");
         | 
| 2611 2690 | 
             
            	}
         | 
| 2612 2691 | 
             
            	p = gzfile_read_raw_until_zero(gz, 0);
         | 
| 2613 2692 | 
             
            	len = p - RSTRING_PTR(gz->z.input);
         | 
| 2614 2693 | 
             
            	gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len);
         | 
| 2615 | 
            -
            	OBJ_TAINT(gz->orig_name);  /* for safe */
         | 
| 2616 2694 | 
             
            	zstream_discard_input(&gz->z, len + 1);
         | 
| 2617 2695 | 
             
                }
         | 
| 2618 2696 | 
             
                if (flags & GZ_FLAG_COMMENT) {
         | 
| 2619 | 
            -
            	if (!gzfile_read_raw_ensure(gz, 1)) {
         | 
| 2697 | 
            +
            	if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
         | 
| 2620 2698 | 
             
            	    rb_raise(cGzError, "unexpected end of file");
         | 
| 2621 2699 | 
             
            	}
         | 
| 2622 2700 | 
             
            	p = gzfile_read_raw_until_zero(gz, 0);
         | 
| 2623 2701 | 
             
            	len = p - RSTRING_PTR(gz->z.input);
         | 
| 2624 2702 | 
             
            	gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
         | 
| 2625 | 
            -
            	OBJ_TAINT(gz->comment);  /* for safe */
         | 
| 2626 2703 | 
             
            	zstream_discard_input(&gz->z, len + 1);
         | 
| 2627 2704 | 
             
                }
         | 
| 2628 2705 |  | 
| @@ -2632,13 +2709,14 @@ gzfile_read_header(struct gzfile *gz) | |
| 2632 2709 | 
             
            }
         | 
| 2633 2710 |  | 
| 2634 2711 | 
             
            static void
         | 
| 2635 | 
            -
            gzfile_check_footer(struct gzfile *gz)
         | 
| 2712 | 
            +
            gzfile_check_footer(struct gzfile *gz, VALUE outbuf)
         | 
| 2636 2713 | 
             
            {
         | 
| 2637 2714 | 
             
                unsigned long crc, length;
         | 
| 2638 2715 |  | 
| 2639 2716 | 
             
                gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
         | 
| 2640 2717 |  | 
| 2641 | 
            -
                 | 
| 2718 | 
            +
                /* 8 is the size of gzip footer */
         | 
| 2719 | 
            +
                if (!gzfile_read_raw_ensure(gz, 8, outbuf)) {
         | 
| 2642 2720 | 
             
            	gzfile_raise(gz, cNoFooter, "footer is not found");
         | 
| 2643 2721 | 
             
                }
         | 
| 2644 2722 |  | 
| @@ -2672,12 +2750,12 @@ gzfile_write(struct gzfile *gz, Bytef *str, long len) | |
| 2672 2750 | 
             
            }
         | 
| 2673 2751 |  | 
| 2674 2752 | 
             
            static long
         | 
| 2675 | 
            -
            gzfile_read_more(struct gzfile *gz)
         | 
| 2753 | 
            +
            gzfile_read_more(struct gzfile *gz, VALUE outbuf)
         | 
| 2676 2754 | 
             
            {
         | 
| 2677 2755 | 
             
                VALUE str;
         | 
| 2678 2756 |  | 
| 2679 2757 | 
             
                while (!ZSTREAM_IS_FINISHED(&gz->z)) {
         | 
| 2680 | 
            -
            	str = gzfile_read_raw(gz);
         | 
| 2758 | 
            +
            	str = gzfile_read_raw(gz, outbuf);
         | 
| 2681 2759 | 
             
            	if (NIL_P(str)) {
         | 
| 2682 2760 | 
             
            	    if (!ZSTREAM_IS_FINISHED(&gz->z)) {
         | 
| 2683 2761 | 
             
            		rb_raise(cGzError, "unexpected end of file");
         | 
| @@ -2689,9 +2767,9 @@ gzfile_read_more(struct gzfile *gz) | |
| 2689 2767 | 
             
            			Z_SYNC_FLUSH);
         | 
| 2690 2768 | 
             
            	    RB_GC_GUARD(str);
         | 
| 2691 2769 | 
             
            	}
         | 
| 2692 | 
            -
            	if (gz->z | 
| 2770 | 
            +
            	if (ZSTREAM_BUF_FILLED(&gz->z) > 0) break;
         | 
| 2693 2771 | 
             
                }
         | 
| 2694 | 
            -
                return gz->z | 
| 2772 | 
            +
                return ZSTREAM_BUF_FILLED(&gz->z);
         | 
| 2695 2773 | 
             
            }
         | 
| 2696 2774 |  | 
| 2697 2775 | 
             
            static void
         | 
| @@ -2702,7 +2780,7 @@ gzfile_calc_crc(struct gzfile *gz, VALUE str) | |
| 2702 2780 | 
             
                }
         | 
| 2703 2781 | 
             
                else {
         | 
| 2704 2782 | 
             
            	gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
         | 
| 2705 | 
            -
             | 
| 2783 | 
            +
            				RSTRING_LEN(str) - gz->ungetc);
         | 
| 2706 2784 | 
             
            	gz->ungetc = 0;
         | 
| 2707 2785 | 
             
                }
         | 
| 2708 2786 | 
             
            }
         | 
| @@ -2712,13 +2790,11 @@ gzfile_newstr(struct gzfile *gz, VALUE str) | |
| 2712 2790 | 
             
            {
         | 
| 2713 2791 | 
             
                if (!gz->enc2) {
         | 
| 2714 2792 | 
             
            	rb_enc_associate(str, gz->enc);
         | 
| 2715 | 
            -
            	OBJ_TAINT(str);  /* for safe */
         | 
| 2716 2793 | 
             
            	return str;
         | 
| 2717 2794 | 
             
                }
         | 
| 2718 2795 | 
             
                if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
         | 
| 2719 2796 | 
             
                    str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
         | 
| 2720 2797 | 
             
            	rb_enc_associate(str, gz->enc);
         | 
| 2721 | 
            -
            	OBJ_TAINT(str);
         | 
| 2722 2798 | 
             
            	return str;
         | 
| 2723 2799 | 
             
                }
         | 
| 2724 2800 | 
             
                return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
         | 
| @@ -2732,16 +2808,16 @@ gzfile_fill(struct gzfile *gz, long len) | |
| 2732 2808 | 
             
                    rb_raise(rb_eArgError, "negative length %ld given", len);
         | 
| 2733 2809 | 
             
                if (len == 0)
         | 
| 2734 2810 | 
             
            	return 0;
         | 
| 2735 | 
            -
                while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z | 
| 2736 | 
            -
            	gzfile_read_more(gz);
         | 
| 2811 | 
            +
                while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
         | 
| 2812 | 
            +
            	gzfile_read_more(gz, Qnil);
         | 
| 2737 2813 | 
             
                }
         | 
| 2738 2814 | 
             
                if (GZFILE_IS_FINISHED(gz)) {
         | 
| 2739 2815 | 
             
            	if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
         | 
| 2740 | 
            -
            	    gzfile_check_footer(gz);
         | 
| 2816 | 
            +
            	    gzfile_check_footer(gz, Qnil);
         | 
| 2741 2817 | 
             
            	}
         | 
| 2742 2818 | 
             
            	return -1;
         | 
| 2743 2819 | 
             
                }
         | 
| 2744 | 
            -
                return len < gz->z | 
| 2820 | 
            +
                return len < ZSTREAM_BUF_FILLED(&gz->z) ? len : ZSTREAM_BUF_FILLED(&gz->z);
         | 
| 2745 2821 | 
             
            }
         | 
| 2746 2822 |  | 
| 2747 2823 | 
             
            static VALUE
         | 
| @@ -2765,9 +2841,6 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) | |
| 2765 2841 | 
             
                if (len < 0)
         | 
| 2766 2842 | 
             
                    rb_raise(rb_eArgError, "negative length %ld given", len);
         | 
| 2767 2843 |  | 
| 2768 | 
            -
                if (!NIL_P(outbuf))
         | 
| 2769 | 
            -
            	OBJ_TAINT(outbuf);
         | 
| 2770 | 
            -
             | 
| 2771 2844 | 
             
                if (len == 0) {
         | 
| 2772 2845 | 
             
                    if (NIL_P(outbuf))
         | 
| 2773 2846 | 
             
                        return rb_str_new(0, 0);
         | 
| @@ -2776,12 +2849,12 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) | |
| 2776 2849 | 
             
                        return outbuf;
         | 
| 2777 2850 | 
             
                    }
         | 
| 2778 2851 | 
             
                }
         | 
| 2779 | 
            -
                while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z | 
| 2780 | 
            -
            	gzfile_read_more(gz);
         | 
| 2852 | 
            +
                while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
         | 
| 2853 | 
            +
            	gzfile_read_more(gz, outbuf);
         | 
| 2781 2854 | 
             
                }
         | 
| 2782 2855 | 
             
                if (GZFILE_IS_FINISHED(gz)) {
         | 
| 2783 2856 | 
             
            	if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
         | 
| 2784 | 
            -
            	    gzfile_check_footer(gz);
         | 
| 2857 | 
            +
            	    gzfile_check_footer(gz, outbuf);
         | 
| 2785 2858 | 
             
            	}
         | 
| 2786 2859 | 
             
                    if (!NIL_P(outbuf))
         | 
| 2787 2860 | 
             
                        rb_str_resize(outbuf, 0);
         | 
| @@ -2794,10 +2867,10 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) | |
| 2794 2867 | 
             
                if (!NIL_P(outbuf)) {
         | 
| 2795 2868 | 
             
                    rb_str_resize(outbuf, RSTRING_LEN(dst));
         | 
| 2796 2869 | 
             
                    memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
         | 
| 2797 | 
            -
            	 | 
| 2870 | 
            +
            	rb_str_resize(dst, 0);
         | 
| 2871 | 
            +
            	rb_gc_force_recycle(dst);
         | 
| 2798 2872 | 
             
            	dst = outbuf;
         | 
| 2799 2873 | 
             
                }
         | 
| 2800 | 
            -
                OBJ_TAINT(dst);  /* for safe */
         | 
| 2801 2874 | 
             
                return dst;
         | 
| 2802 2875 | 
             
            }
         | 
| 2803 2876 |  | 
| @@ -2807,11 +2880,11 @@ gzfile_read_all(struct gzfile *gz) | |
| 2807 2880 | 
             
                VALUE dst;
         | 
| 2808 2881 |  | 
| 2809 2882 | 
             
                while (!ZSTREAM_IS_FINISHED(&gz->z)) {
         | 
| 2810 | 
            -
            	gzfile_read_more(gz);
         | 
| 2883 | 
            +
            	gzfile_read_more(gz, Qnil);
         | 
| 2811 2884 | 
             
                }
         | 
| 2812 2885 | 
             
                if (GZFILE_IS_FINISHED(gz)) {
         | 
| 2813 2886 | 
             
            	if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
         | 
| 2814 | 
            -
            	    gzfile_check_footer(gz);
         | 
| 2887 | 
            +
            	    gzfile_check_footer(gz, Qnil);
         | 
| 2815 2888 | 
             
            	}
         | 
| 2816 2889 | 
             
            	return rb_str_new(0, 0);
         | 
| 2817 2890 | 
             
                }
         | 
| @@ -2819,7 +2892,6 @@ gzfile_read_all(struct gzfile *gz) | |
| 2819 2892 | 
             
                dst = zstream_detach_buffer(&gz->z);
         | 
| 2820 2893 | 
             
                if (NIL_P(dst)) return dst;
         | 
| 2821 2894 | 
             
                gzfile_calc_crc(gz, dst);
         | 
| 2822 | 
            -
                OBJ_TAINT(dst);
         | 
| 2823 2895 | 
             
                return gzfile_newstr(gz, dst);
         | 
| 2824 2896 | 
             
            }
         | 
| 2825 2897 |  | 
| @@ -2830,12 +2902,12 @@ gzfile_getc(struct gzfile *gz) | |
| 2830 2902 | 
             
                int len;
         | 
| 2831 2903 |  | 
| 2832 2904 | 
             
                len = rb_enc_mbmaxlen(gz->enc);
         | 
| 2833 | 
            -
                while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z | 
| 2834 | 
            -
            	gzfile_read_more(gz);
         | 
| 2905 | 
            +
                while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
         | 
| 2906 | 
            +
            	gzfile_read_more(gz, Qnil);
         | 
| 2835 2907 | 
             
                }
         | 
| 2836 2908 | 
             
                if (GZFILE_IS_FINISHED(gz)) {
         | 
| 2837 2909 | 
             
            	if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
         | 
| 2838 | 
            -
            	    gzfile_check_footer(gz);
         | 
| 2910 | 
            +
            	    gzfile_check_footer(gz, Qnil);
         | 
| 2839 2911 | 
             
            	}
         | 
| 2840 2912 | 
             
            	return Qnil;
         | 
| 2841 2913 | 
             
                }
         | 
| @@ -2843,22 +2915,18 @@ gzfile_getc(struct gzfile *gz) | |
| 2843 2915 | 
             
                if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
         | 
| 2844 2916 | 
             
            	const unsigned char *ss, *sp, *se;
         | 
| 2845 2917 | 
             
            	unsigned char *ds, *dp, *de;
         | 
| 2918 | 
            +
            	VALUE cbuf = rb_enc_str_new(0, GZFILE_CBUF_CAPA, gz->enc);
         | 
| 2846 2919 |  | 
| 2847 | 
            -
            	if (!gz->cbuf) {
         | 
| 2848 | 
            -
            	    gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA);
         | 
| 2849 | 
            -
            	}
         | 
| 2850 2920 | 
             
                    ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
         | 
| 2851 | 
            -
                    se = sp + gz->z | 
| 2852 | 
            -
                    ds = dp = (unsigned char *) | 
| 2921 | 
            +
                    se = sp + ZSTREAM_BUF_FILLED(&gz->z);
         | 
| 2922 | 
            +
                    ds = dp = (unsigned char *)RSTRING_PTR(cbuf);
         | 
| 2853 2923 | 
             
                    de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
         | 
| 2854 2924 | 
             
                    (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
         | 
| 2855 2925 | 
             
                    rb_econv_check_error(gz->ec);
         | 
| 2856 2926 | 
             
            	dst = zstream_shift_buffer(&gz->z, sp - ss);
         | 
| 2857 2927 | 
             
            	gzfile_calc_crc(gz, dst);
         | 
| 2858 | 
            -
            	 | 
| 2859 | 
            -
            	 | 
| 2860 | 
            -
            	OBJ_TAINT(dst);
         | 
| 2861 | 
            -
            	return dst;
         | 
| 2928 | 
            +
            	rb_str_resize(cbuf, dp - ds);
         | 
| 2929 | 
            +
            	return cbuf;
         | 
| 2862 2930 | 
             
                }
         | 
| 2863 2931 | 
             
                else {
         | 
| 2864 2932 | 
             
            	buf = gz->z.buf;
         | 
| @@ -2905,7 +2973,7 @@ gzfile_writer_end(struct gzfile *gz) | |
| 2905 2973 | 
             
                if (ZSTREAM_IS_CLOSING(&gz->z)) return;
         | 
| 2906 2974 | 
             
                gz->z.flags |= ZSTREAM_FLAG_CLOSING;
         | 
| 2907 2975 |  | 
| 2908 | 
            -
                rb_ensure(gzfile_writer_end_run, (VALUE)gz,  | 
| 2976 | 
            +
                rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
         | 
| 2909 2977 | 
             
            }
         | 
| 2910 2978 |  | 
| 2911 2979 | 
             
            static VALUE
         | 
| @@ -2915,7 +2983,7 @@ gzfile_reader_end_run(VALUE arg) | |
| 2915 2983 |  | 
| 2916 2984 | 
             
                if (GZFILE_IS_FINISHED(gz)
         | 
| 2917 2985 | 
             
            	&& !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
         | 
| 2918 | 
            -
            	gzfile_check_footer(gz);
         | 
| 2986 | 
            +
            	gzfile_check_footer(gz, Qnil);
         | 
| 2919 2987 | 
             
                }
         | 
| 2920 2988 |  | 
| 2921 2989 | 
             
                return Qnil;
         | 
| @@ -2927,7 +2995,7 @@ gzfile_reader_end(struct gzfile *gz) | |
| 2927 2995 | 
             
                if (ZSTREAM_IS_CLOSING(&gz->z)) return;
         | 
| 2928 2996 | 
             
                gz->z.flags |= ZSTREAM_FLAG_CLOSING;
         | 
| 2929 2997 |  | 
| 2930 | 
            -
                rb_ensure(gzfile_reader_end_run, (VALUE)gz,  | 
| 2998 | 
            +
                rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
         | 
| 2931 2999 | 
             
            }
         | 
| 2932 3000 |  | 
| 2933 3001 | 
             
            static void
         | 
| @@ -2952,12 +3020,11 @@ gzfile_reader_get_unused(struct gzfile *gz) | |
| 2952 3020 | 
             
                if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
         | 
| 2953 3021 | 
             
                if (!GZFILE_IS_FINISHED(gz)) return Qnil;
         | 
| 2954 3022 | 
             
                if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
         | 
| 2955 | 
            -
            	gzfile_check_footer(gz);
         | 
| 3023 | 
            +
            	gzfile_check_footer(gz, Qnil);
         | 
| 2956 3024 | 
             
                }
         | 
| 2957 3025 | 
             
                if (NIL_P(gz->z.input)) return Qnil;
         | 
| 2958 3026 |  | 
| 2959 3027 | 
             
                str = rb_str_resurrect(gz->z.input);
         | 
| 2960 | 
            -
                OBJ_TAINT(str);  /* for safe */
         | 
| 2961 3028 | 
             
                return str;
         | 
| 2962 3029 | 
             
            }
         | 
| 2963 3030 |  | 
| @@ -3024,7 +3091,7 @@ static VALUE | |
| 3024 3091 | 
             
            new_wrap(VALUE tmp)
         | 
| 3025 3092 | 
             
            {
         | 
| 3026 3093 | 
             
                new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp;
         | 
| 3027 | 
            -
                return  | 
| 3094 | 
            +
                return rb_class_new_instance_kw(arg->argc, arg->argv, arg->klass, RB_PASS_CALLED_KEYWORDS);
         | 
| 3028 3095 | 
             
            }
         | 
| 3029 3096 |  | 
| 3030 3097 | 
             
            static VALUE
         | 
| @@ -3057,7 +3124,7 @@ gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error) | |
| 3057 3124 | 
             
            	}
         | 
| 3058 3125 | 
             
                }
         | 
| 3059 3126 | 
             
                else {
         | 
| 3060 | 
            -
            	obj =  | 
| 3127 | 
            +
            	obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
         | 
| 3061 3128 | 
             
                }
         | 
| 3062 3129 |  | 
| 3063 3130 | 
             
                if (rb_block_given_p()) {
         | 
| @@ -3174,7 +3241,6 @@ rb_gzfile_orig_name(VALUE obj) | |
| 3174 3241 | 
             
                if (!NIL_P(str)) {
         | 
| 3175 3242 | 
             
            	str = rb_str_dup(str);
         | 
| 3176 3243 | 
             
                }
         | 
| 3177 | 
            -
                OBJ_TAINT(str);  /* for safe */
         | 
| 3178 3244 | 
             
                return str;
         | 
| 3179 3245 | 
             
            }
         | 
| 3180 3246 |  | 
| @@ -3191,7 +3257,6 @@ rb_gzfile_comment(VALUE obj) | |
| 3191 3257 | 
             
                if (!NIL_P(str)) {
         | 
| 3192 3258 | 
             
            	str = rb_str_dup(str);
         | 
| 3193 3259 | 
             
                }
         | 
| 3194 | 
            -
                OBJ_TAINT(str);  /* for safe */
         | 
| 3195 3260 | 
             
                return str;
         | 
| 3196 3261 | 
             
            }
         | 
| 3197 3262 |  | 
| @@ -3250,6 +3315,7 @@ rb_gzfile_set_mtime(VALUE obj, VALUE mtime) | |
| 3250 3315 |  | 
| 3251 3316 | 
             
                val = rb_Integer(mtime);
         | 
| 3252 3317 | 
             
                gz->mtime = NUM2UINT(val);
         | 
| 3318 | 
            +
                gz->z.flags |= GZFILE_FLAG_MTIME_IS_SET;
         | 
| 3253 3319 |  | 
| 3254 3320 | 
             
                return mtime;
         | 
| 3255 3321 | 
             
            }
         | 
| @@ -3422,7 +3488,14 @@ static VALUE | |
| 3422 3488 | 
             
            rb_gzfile_total_out(VALUE obj)
         | 
| 3423 3489 | 
             
            {
         | 
| 3424 3490 | 
             
                struct gzfile *gz = get_gzfile(obj);
         | 
| 3425 | 
            -
                 | 
| 3491 | 
            +
                uLong total_out = gz->z.stream.total_out;
         | 
| 3492 | 
            +
                long buf_filled = ZSTREAM_BUF_FILLED(&gz->z);
         | 
| 3493 | 
            +
             | 
| 3494 | 
            +
                if (total_out >= (uLong)buf_filled) {
         | 
| 3495 | 
            +
                    return rb_uint2inum(total_out - buf_filled);
         | 
| 3496 | 
            +
                } else {
         | 
| 3497 | 
            +
                    return LONG2FIX(-(buf_filled - (long)total_out));
         | 
| 3498 | 
            +
                }
         | 
| 3426 3499 | 
             
            }
         | 
| 3427 3500 |  | 
| 3428 3501 | 
             
            /*
         | 
| @@ -3588,18 +3661,23 @@ rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj) | |
| 3588 3661 | 
             
             * Same as IO.
         | 
| 3589 3662 | 
             
             */
         | 
| 3590 3663 | 
             
            static VALUE
         | 
| 3591 | 
            -
            rb_gzwriter_write(VALUE  | 
| 3664 | 
            +
            rb_gzwriter_write(int argc, VALUE *argv, VALUE obj)
         | 
| 3592 3665 | 
             
            {
         | 
| 3593 3666 | 
             
                struct gzfile *gz = get_gzfile(obj);
         | 
| 3594 | 
            -
             | 
| 3595 | 
            -
             | 
| 3596 | 
            -
             | 
| 3597 | 
            -
             | 
| 3598 | 
            -
            	 | 
| 3667 | 
            +
                size_t total = 0;
         | 
| 3668 | 
            +
             | 
| 3669 | 
            +
                while (argc-- > 0) {
         | 
| 3670 | 
            +
            	VALUE str = *argv++;
         | 
| 3671 | 
            +
            	if (!RB_TYPE_P(str, T_STRING))
         | 
| 3672 | 
            +
            	    str = rb_obj_as_string(str);
         | 
| 3673 | 
            +
            	if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
         | 
| 3674 | 
            +
            	    str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
         | 
| 3675 | 
            +
            	}
         | 
| 3676 | 
            +
            	gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
         | 
| 3677 | 
            +
            	total += RSTRING_LEN(str);
         | 
| 3678 | 
            +
            	RB_GC_GUARD(str);
         | 
| 3599 3679 | 
             
                }
         | 
| 3600 | 
            -
                 | 
| 3601 | 
            -
                RB_GC_GUARD(str);
         | 
| 3602 | 
            -
                return INT2FIX(RSTRING_LEN(str));
         | 
| 3680 | 
            +
                return SIZET2NUM(total);
         | 
| 3603 3681 | 
             
            }
         | 
| 3604 3682 |  | 
| 3605 3683 | 
             
            /*
         | 
| @@ -3714,6 +3792,60 @@ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass) | |
| 3714 3792 | 
             
                return gzfile_s_open(argc, argv, klass, "rb");
         | 
| 3715 3793 | 
             
            }
         | 
| 3716 3794 |  | 
| 3795 | 
            +
            /*
         | 
| 3796 | 
            +
             * Document-method: Zlib::GzipReader.zcat
         | 
| 3797 | 
            +
             *
         | 
| 3798 | 
            +
             * call-seq:
         | 
| 3799 | 
            +
             *   Zlib::GzipReader.zcat(io, options = {}, &block) => nil
         | 
| 3800 | 
            +
             *   Zlib::GzipReader.zcat(io, options = {}) => string
         | 
| 3801 | 
            +
             *
         | 
| 3802 | 
            +
             * Decompresses all gzip data in the +io+, handling multiple gzip
         | 
| 3803 | 
            +
             * streams until the end of the +io+.  There should not be any non-gzip
         | 
| 3804 | 
            +
             * data after the gzip streams.
         | 
| 3805 | 
            +
             *
         | 
| 3806 | 
            +
             * If a block is given, it is yielded strings of uncompressed data,
         | 
| 3807 | 
            +
             * and the method returns +nil+.
         | 
| 3808 | 
            +
             * If a block is not given, the method returns the concatenation of
         | 
| 3809 | 
            +
             * all uncompressed data in all gzip streams.
         | 
| 3810 | 
            +
             */
         | 
| 3811 | 
            +
            static VALUE
         | 
| 3812 | 
            +
            rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
         | 
| 3813 | 
            +
            {
         | 
| 3814 | 
            +
                VALUE io, unused, obj, buf=0, tmpbuf;
         | 
| 3815 | 
            +
                long pos;
         | 
| 3816 | 
            +
             | 
| 3817 | 
            +
                rb_check_arity(argc, 1, 2);
         | 
| 3818 | 
            +
                io = argv[0];
         | 
| 3819 | 
            +
             | 
| 3820 | 
            +
                do {
         | 
| 3821 | 
            +
                    obj = rb_funcallv(klass, rb_intern("new"), argc, argv);
         | 
| 3822 | 
            +
                    if (rb_block_given_p()) {
         | 
| 3823 | 
            +
                       rb_gzreader_each(0, 0, obj);
         | 
| 3824 | 
            +
                    }
         | 
| 3825 | 
            +
                    else {
         | 
| 3826 | 
            +
                        if (!buf) {
         | 
| 3827 | 
            +
                            buf = rb_str_new(0, 0);
         | 
| 3828 | 
            +
                        }
         | 
| 3829 | 
            +
                        tmpbuf = gzfile_read_all(get_gzfile(obj));
         | 
| 3830 | 
            +
                        rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
         | 
| 3831 | 
            +
                    }
         | 
| 3832 | 
            +
             | 
| 3833 | 
            +
                    rb_gzreader_read(0, 0, obj);
         | 
| 3834 | 
            +
                    pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0));
         | 
| 3835 | 
            +
                    unused = rb_gzreader_unused(obj);
         | 
| 3836 | 
            +
                    rb_gzfile_finish(obj);
         | 
| 3837 | 
            +
                    if (!NIL_P(unused)) {
         | 
| 3838 | 
            +
                        pos -= NUM2LONG(rb_funcall(unused, rb_intern("length"), 0));
         | 
| 3839 | 
            +
                        rb_funcall(io, rb_intern("pos="), 1, LONG2NUM(pos));
         | 
| 3840 | 
            +
                    }
         | 
| 3841 | 
            +
                } while (pos < NUM2LONG(rb_funcall(io, rb_intern("size"), 0)));
         | 
| 3842 | 
            +
             | 
| 3843 | 
            +
                if (rb_block_given_p()) {
         | 
| 3844 | 
            +
                    return Qnil;
         | 
| 3845 | 
            +
                }
         | 
| 3846 | 
            +
                return buf;
         | 
| 3847 | 
            +
            }
         | 
| 3848 | 
            +
             | 
| 3717 3849 | 
             
            /*
         | 
| 3718 3850 | 
             
             * Document-method: Zlib::GzipReader.new
         | 
| 3719 3851 | 
             
             *
         | 
| @@ -3748,7 +3880,7 @@ rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj) | |
| 3748 3880 | 
             
                }
         | 
| 3749 3881 | 
             
                gz->io = io;
         | 
| 3750 3882 | 
             
                ZSTREAM_READY(&gz->z);
         | 
| 3751 | 
            -
                gzfile_read_header(gz);
         | 
| 3883 | 
            +
                gzfile_read_header(gz, Qnil);
         | 
| 3752 3884 | 
             
                rb_gzfile_ecopts(gz, opt);
         | 
| 3753 3885 |  | 
| 3754 3886 | 
             
                if (rb_respond_to(io, id_path)) {
         | 
| @@ -3940,20 +4072,6 @@ rb_gzreader_each_byte(VALUE obj) | |
| 3940 4072 | 
             
                return Qnil;
         | 
| 3941 4073 | 
             
            }
         | 
| 3942 4074 |  | 
| 3943 | 
            -
            /*
         | 
| 3944 | 
            -
             * Document-method: Zlib::GzipReader#bytes
         | 
| 3945 | 
            -
             *
         | 
| 3946 | 
            -
             *  This is a deprecated alias for <code>each_byte</code>.
         | 
| 3947 | 
            -
             */
         | 
| 3948 | 
            -
            static VALUE
         | 
| 3949 | 
            -
            rb_gzreader_bytes(VALUE obj)
         | 
| 3950 | 
            -
            {
         | 
| 3951 | 
            -
                rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
         | 
| 3952 | 
            -
                if (!rb_block_given_p())
         | 
| 3953 | 
            -
            	return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
         | 
| 3954 | 
            -
                return rb_gzreader_each_byte(obj);
         | 
| 3955 | 
            -
            }
         | 
| 3956 | 
            -
             | 
| 3957 4075 | 
             
            /*
         | 
| 3958 4076 | 
             
             * Document-method: Zlib::GzipReader#ungetc
         | 
| 3959 4077 | 
             
             *
         | 
| @@ -3996,20 +4114,20 @@ gzreader_skip_linebreaks(struct gzfile *gz) | |
| 3996 4114 | 
             
                char *p;
         | 
| 3997 4115 | 
             
                int n;
         | 
| 3998 4116 |  | 
| 3999 | 
            -
                while (gz->z | 
| 4117 | 
            +
                while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
         | 
| 4000 4118 | 
             
            	if (GZFILE_IS_FINISHED(gz)) return;
         | 
| 4001 | 
            -
            	gzfile_read_more(gz);
         | 
| 4119 | 
            +
            	gzfile_read_more(gz, Qnil);
         | 
| 4002 4120 | 
             
                }
         | 
| 4003 4121 | 
             
                n = 0;
         | 
| 4004 4122 | 
             
                p = RSTRING_PTR(gz->z.buf);
         | 
| 4005 4123 |  | 
| 4006 4124 | 
             
                while (n++, *(p++) == '\n') {
         | 
| 4007 | 
            -
            	if (n >= gz->z | 
| 4125 | 
            +
            	if (n >= ZSTREAM_BUF_FILLED(&gz->z)) {
         | 
| 4008 4126 | 
             
            	    str = zstream_detach_buffer(&gz->z);
         | 
| 4009 4127 | 
             
            	    gzfile_calc_crc(gz, str);
         | 
| 4010 | 
            -
            	    while (gz->z | 
| 4128 | 
            +
            	    while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
         | 
| 4011 4129 | 
             
            		if (GZFILE_IS_FINISHED(gz)) return;
         | 
| 4012 | 
            -
            		gzfile_read_more(gz);
         | 
| 4130 | 
            +
            		gzfile_read_more(gz, Qnil);
         | 
| 4013 4131 | 
             
            	    }
         | 
| 4014 4132 | 
             
            	    n = 0;
         | 
| 4015 4133 | 
             
            	    p = RSTRING_PTR(gz->z.buf);
         | 
| @@ -4031,7 +4149,7 @@ static long | |
| 4031 4149 | 
             
            gzreader_charboundary(struct gzfile *gz, long n)
         | 
| 4032 4150 | 
             
            {
         | 
| 4033 4151 | 
             
                char *s = RSTRING_PTR(gz->z.buf);
         | 
| 4034 | 
            -
                char *e = s + gz->z | 
| 4152 | 
            +
                char *e = s + ZSTREAM_BUF_FILLED(&gz->z);
         | 
| 4035 4153 | 
             
                char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
         | 
| 4036 4154 | 
             
                long l = p - s;
         | 
| 4037 4155 | 
             
                if (l < n) {
         | 
| @@ -4126,25 +4244,25 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) | |
| 4126 4244 | 
             
            	gzreader_skip_linebreaks(gz);
         | 
| 4127 4245 | 
             
                }
         | 
| 4128 4246 |  | 
| 4129 | 
            -
                while (gz->z | 
| 4247 | 
            +
                while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) {
         | 
| 4130 4248 | 
             
            	if (ZSTREAM_IS_FINISHED(&gz->z)) {
         | 
| 4131 | 
            -
            	    if (gz->z | 
| 4249 | 
            +
            	    if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
         | 
| 4132 4250 | 
             
            	    return gzfile_read(gz, rslen);
         | 
| 4133 4251 | 
             
            	}
         | 
| 4134 | 
            -
            	gzfile_read_more(gz);
         | 
| 4252 | 
            +
            	gzfile_read_more(gz, Qnil);
         | 
| 4135 4253 | 
             
                }
         | 
| 4136 4254 |  | 
| 4137 4255 | 
             
                p = RSTRING_PTR(gz->z.buf);
         | 
| 4138 4256 | 
             
                n = rslen;
         | 
| 4139 4257 | 
             
                for (;;) {
         | 
| 4140 4258 | 
             
            	long filled;
         | 
| 4141 | 
            -
            	if (n > gz->z | 
| 4259 | 
            +
            	if (n > ZSTREAM_BUF_FILLED(&gz->z)) {
         | 
| 4142 4260 | 
             
            	    if (ZSTREAM_IS_FINISHED(&gz->z)) break;
         | 
| 4143 | 
            -
            	    gzfile_read_more(gz);
         | 
| 4261 | 
            +
            	    gzfile_read_more(gz, Qnil);
         | 
| 4144 4262 | 
             
            	    p = RSTRING_PTR(gz->z.buf) + n - rslen;
         | 
| 4145 4263 | 
             
            	}
         | 
| 4146 4264 | 
             
            	if (!rspara) rscheck(rsptr, rslen, rs);
         | 
| 4147 | 
            -
            	filled = gz->z | 
| 4265 | 
            +
            	filled = ZSTREAM_BUF_FILLED(&gz->z);
         | 
| 4148 4266 | 
             
            	if (limit > 0 && filled >= limit) {
         | 
| 4149 4267 | 
             
            	    filled = limit;
         | 
| 4150 4268 | 
             
            	}
         | 
| @@ -4161,7 +4279,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) | |
| 4161 4279 | 
             
            	    p++, n++;
         | 
| 4162 4280 | 
             
            	}
         | 
| 4163 4281 | 
             
                }
         | 
| 4164 | 
            -
                if (maxlen > 1 && n == limit && (gz->z | 
| 4282 | 
            +
                if (maxlen > 1 && n == limit && (ZSTREAM_BUF_FILLED(&gz->z) > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
         | 
| 4165 4283 | 
             
            	n = gzreader_charboundary(gz, n);
         | 
| 4166 4284 | 
             
                }
         | 
| 4167 4285 |  | 
| @@ -4180,6 +4298,8 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) | |
| 4180 4298 | 
             
             * Document-method: Zlib::GzipReader#gets
         | 
| 4181 4299 | 
             
             *
         | 
| 4182 4300 | 
             
             * See Zlib::GzipReader documentation for a description.
         | 
| 4301 | 
            +
             * However, note that this method can return +nil+ even if
         | 
| 4302 | 
            +
             * #eof? returns false, unlike the behavior of File#gets.
         | 
| 4183 4303 | 
             
             */
         | 
| 4184 4304 | 
             
            static VALUE
         | 
| 4185 4305 | 
             
            rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
         | 
| @@ -4226,20 +4346,6 @@ rb_gzreader_each(int argc, VALUE *argv, VALUE obj) | |
| 4226 4346 | 
             
                return obj;
         | 
| 4227 4347 | 
             
            }
         | 
| 4228 4348 |  | 
| 4229 | 
            -
            /*
         | 
| 4230 | 
            -
             * Document-method: Zlib::GzipReader#lines
         | 
| 4231 | 
            -
             *
         | 
| 4232 | 
            -
             *  This is a deprecated alias for <code>each_line</code>.
         | 
| 4233 | 
            -
             */
         | 
| 4234 | 
            -
            static VALUE
         | 
| 4235 | 
            -
            rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
         | 
| 4236 | 
            -
            {
         | 
| 4237 | 
            -
                rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
         | 
| 4238 | 
            -
                if (!rb_block_given_p())
         | 
| 4239 | 
            -
            	return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
         | 
| 4240 | 
            -
                return rb_gzreader_each(argc, argv, obj);
         | 
| 4241 | 
            -
            }
         | 
| 4242 | 
            -
             | 
| 4243 4349 | 
             
            /*
         | 
| 4244 4350 | 
             
             * Document-method: Zlib::GzipReader#readlines
         | 
| 4245 4351 | 
             
             *
         | 
| @@ -4267,6 +4373,20 @@ rb_gzreader_external_encoding(VALUE self) | |
| 4267 4373 | 
             
                return rb_enc_from_encoding(get_gzfile(self)->enc);
         | 
| 4268 4374 | 
             
            }
         | 
| 4269 4375 |  | 
| 4376 | 
            +
            static VALUE
         | 
| 4377 | 
            +
            zlib_gzip_end_rescue(VALUE arg)
         | 
| 4378 | 
            +
            {
         | 
| 4379 | 
            +
                struct gzfile *gz = (struct gzfile *)arg;
         | 
| 4380 | 
            +
                gz->end(gz);
         | 
| 4381 | 
            +
                return Qnil;
         | 
| 4382 | 
            +
            }
         | 
| 4383 | 
            +
             | 
| 4384 | 
            +
            static VALUE
         | 
| 4385 | 
            +
            zlib_gzip_ensure(VALUE arg)
         | 
| 4386 | 
            +
            {
         | 
| 4387 | 
            +
                return rb_rescue(zlib_gzip_end_rescue, arg, NULL, Qnil);
         | 
| 4388 | 
            +
            }
         | 
| 4389 | 
            +
             | 
| 4270 4390 | 
             
            static void
         | 
| 4271 4391 | 
             
            zlib_gzip_end(struct gzfile *gz)
         | 
| 4272 4392 | 
             
            {
         | 
| @@ -4276,9 +4396,8 @@ zlib_gzip_end(struct gzfile *gz) | |
| 4276 4396 | 
             
                zstream_end(&gz->z);
         | 
| 4277 4397 | 
             
            }
         | 
| 4278 4398 |  | 
| 4279 | 
            -
            #define OPTHASH_GIVEN_P(opts) \
         | 
| 4280 | 
            -
                (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
         | 
| 4281 4399 | 
             
            static ID id_level, id_strategy;
         | 
| 4400 | 
            +
            static VALUE zlib_gzip_run(VALUE arg);
         | 
| 4282 4401 |  | 
| 4283 4402 | 
             
            /*
         | 
| 4284 4403 | 
             
             * call-seq:
         | 
| @@ -4307,9 +4426,8 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass) | |
| 4307 4426 | 
             
            {
         | 
| 4308 4427 | 
             
                struct gzfile gz0;
         | 
| 4309 4428 | 
             
                struct gzfile *gz = &gz0;
         | 
| 4310 | 
            -
                long len;
         | 
| 4311 4429 | 
             
                int err;
         | 
| 4312 | 
            -
                VALUE src, opts, level=Qnil, strategy=Qnil;
         | 
| 4430 | 
            +
                VALUE src, opts, level=Qnil, strategy=Qnil, args[2];
         | 
| 4313 4431 |  | 
| 4314 4432 | 
             
                if (OPTHASH_GIVEN_P(opts)) {
         | 
| 4315 4433 | 
             
            	ID keyword_ids[2];
         | 
| @@ -4331,9 +4449,23 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass) | |
| 4331 4449 | 
             
                err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
         | 
| 4332 4450 | 
             
            		       -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
         | 
| 4333 4451 | 
             
                if (err != Z_OK) {
         | 
| 4452 | 
            +
            	zlib_gzip_end(gz);
         | 
| 4334 4453 | 
             
            	raise_zlib_error(err, gz->z.stream.msg);
         | 
| 4335 4454 | 
             
                }
         | 
| 4336 4455 | 
             
                ZSTREAM_READY(&gz->z);
         | 
| 4456 | 
            +
                args[0] = (VALUE)gz;
         | 
| 4457 | 
            +
                args[1] = src;
         | 
| 4458 | 
            +
                return rb_ensure(zlib_gzip_run, (VALUE)args, zlib_gzip_ensure, (VALUE)gz);
         | 
| 4459 | 
            +
            }
         | 
| 4460 | 
            +
             | 
| 4461 | 
            +
            static VALUE
         | 
| 4462 | 
            +
            zlib_gzip_run(VALUE arg)
         | 
| 4463 | 
            +
            {
         | 
| 4464 | 
            +
                VALUE *args = (VALUE *)arg;
         | 
| 4465 | 
            +
                struct gzfile *gz = (struct gzfile *)args[0];
         | 
| 4466 | 
            +
                VALUE src = args[1];
         | 
| 4467 | 
            +
                long len;
         | 
| 4468 | 
            +
             | 
| 4337 4469 | 
             
                gzfile_make_header(gz);
         | 
| 4338 4470 | 
             
                len = RSTRING_LEN(src);
         | 
| 4339 4471 | 
             
                if (len > 0) {
         | 
| @@ -4349,10 +4481,11 @@ static void | |
| 4349 4481 | 
             
            zlib_gunzip_end(struct gzfile *gz)
         | 
| 4350 4482 | 
             
            {
         | 
| 4351 4483 | 
             
                gz->z.flags |= ZSTREAM_FLAG_CLOSING;
         | 
| 4352 | 
            -
                gzfile_check_footer(gz);
         | 
| 4353 4484 | 
             
                zstream_end(&gz->z);
         | 
| 4354 4485 | 
             
            }
         | 
| 4355 4486 |  | 
| 4487 | 
            +
            static VALUE zlib_gunzip_run(VALUE arg);
         | 
| 4488 | 
            +
             | 
| 4356 4489 | 
             
            /*
         | 
| 4357 4490 | 
             
             * call-seq:
         | 
| 4358 4491 | 
             
             *   Zlib.gunzip(src) -> String
         | 
| @@ -4377,7 +4510,6 @@ zlib_gunzip(VALUE klass, VALUE src) | |
| 4377 4510 | 
             
                struct gzfile gz0;
         | 
| 4378 4511 | 
             
                struct gzfile *gz = &gz0;
         | 
| 4379 4512 | 
             
                int err;
         | 
| 4380 | 
            -
                VALUE dst;
         | 
| 4381 4513 |  | 
| 4382 4514 | 
             
                StringValue(src);
         | 
| 4383 4515 |  | 
| @@ -4389,15 +4521,25 @@ zlib_gunzip(VALUE klass, VALUE src) | |
| 4389 4521 | 
             
                gz->io = Qundef;
         | 
| 4390 4522 | 
             
                gz->z.input = src;
         | 
| 4391 4523 | 
             
                ZSTREAM_READY(&gz->z);
         | 
| 4392 | 
            -
                 | 
| 4524 | 
            +
                return rb_ensure(zlib_gunzip_run, (VALUE)gz, zlib_gzip_ensure, (VALUE)gz);
         | 
| 4525 | 
            +
            }
         | 
| 4526 | 
            +
             | 
| 4527 | 
            +
            static VALUE
         | 
| 4528 | 
            +
            zlib_gunzip_run(VALUE arg)
         | 
| 4529 | 
            +
            {
         | 
| 4530 | 
            +
                struct gzfile *gz = (struct gzfile *)arg;
         | 
| 4531 | 
            +
                VALUE dst;
         | 
| 4532 | 
            +
             | 
| 4533 | 
            +
                gzfile_read_header(gz, Qnil);
         | 
| 4393 4534 | 
             
                dst = zstream_detach_buffer(&gz->z);
         | 
| 4394 4535 | 
             
                gzfile_calc_crc(gz, dst);
         | 
| 4395 | 
            -
             | 
| 4396 | 
            -
             | 
| 4397 | 
            -
             | 
| 4398 | 
            -
                if (NIL_P(gz->z.input))
         | 
| 4536 | 
            +
                if (!ZSTREAM_IS_FINISHED(&gz->z)) {
         | 
| 4537 | 
            +
            	rb_raise(cGzError, "unexpected end of file");
         | 
| 4538 | 
            +
                }
         | 
| 4539 | 
            +
                if (NIL_P(gz->z.input)) {
         | 
| 4399 4540 | 
             
            	rb_raise(cNoFooter, "footer is not found");
         | 
| 4400 | 
            -
                 | 
| 4541 | 
            +
                }
         | 
| 4542 | 
            +
                gzfile_check_footer(gz, Qnil);
         | 
| 4401 4543 | 
             
                return dst;
         | 
| 4402 4544 | 
             
            }
         | 
| 4403 4545 |  | 
| @@ -4406,6 +4548,11 @@ zlib_gunzip(VALUE klass, VALUE src) | |
| 4406 4548 | 
             
            void
         | 
| 4407 4549 | 
             
            Init_zlib(void)
         | 
| 4408 4550 | 
             
            {
         | 
| 4551 | 
            +
            #if HAVE_RB_EXT_RACTOR_SAFE
         | 
| 4552 | 
            +
                rb_ext_ractor_safe(true);
         | 
| 4553 | 
            +
            #endif
         | 
| 4554 | 
            +
             | 
| 4555 | 
            +
            #undef rb_intern
         | 
| 4409 4556 | 
             
                VALUE mZlib, cZStream, cDeflate, cInflate;
         | 
| 4410 4557 | 
             
            #if GZIP_SUPPORT
         | 
| 4411 4558 | 
             
                VALUE cGzipFile, cGzipWriter, cGzipReader;
         | 
| @@ -4499,7 +4646,7 @@ Init_zlib(void) | |
| 4499 4646 | 
             
                rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
         | 
| 4500 4647 | 
             
                rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
         | 
| 4501 4648 | 
             
                rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
         | 
| 4502 | 
            -
                rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
         | 
| 4649 | 
            +
                rb_define_method(cInflate, "inflate", rb_inflate_inflate, -1);
         | 
| 4503 4650 | 
             
                rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
         | 
| 4504 4651 | 
             
                rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
         | 
| 4505 4652 | 
             
                rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
         | 
| @@ -4640,7 +4787,7 @@ Init_zlib(void) | |
| 4640 4787 | 
             
                rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
         | 
| 4641 4788 | 
             
                rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
         | 
| 4642 4789 | 
             
                rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
         | 
| 4643 | 
            -
                rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
         | 
| 4790 | 
            +
                rb_define_method(cGzipWriter, "write", rb_gzwriter_write, -1);
         | 
| 4644 4791 | 
             
                rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
         | 
| 4645 4792 | 
             
                rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
         | 
| 4646 4793 | 
             
                rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
         | 
| @@ -4648,6 +4795,7 @@ Init_zlib(void) | |
| 4648 4795 | 
             
                rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
         | 
| 4649 4796 |  | 
| 4650 4797 | 
             
                rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
         | 
| 4798 | 
            +
                rb_define_singleton_method(cGzipReader, "zcat", rb_gzreader_s_zcat, -1);
         | 
| 4651 4799 | 
             
                rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
         | 
| 4652 4800 | 
             
                rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
         | 
| 4653 4801 | 
             
                rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
         | 
| @@ -4660,14 +4808,12 @@ Init_zlib(void) | |
| 4660 4808 | 
             
                rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
         | 
| 4661 4809 | 
             
                rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
         | 
| 4662 4810 | 
             
                rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
         | 
| 4663 | 
            -
                rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
         | 
| 4664 4811 | 
             
                rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
         | 
| 4665 4812 | 
             
                rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
         | 
| 4666 4813 | 
             
                rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
         | 
| 4667 4814 | 
             
                rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
         | 
| 4668 4815 | 
             
                rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
         | 
| 4669 4816 | 
             
                rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
         | 
| 4670 | 
            -
                rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
         | 
| 4671 4817 | 
             
                rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
         | 
| 4672 4818 | 
             
                rb_define_method(cGzipReader, "external_encoding", rb_gzreader_external_encoding, 0);
         | 
| 4673 4819 |  | 
| @@ -4709,6 +4855,7 @@ Init_zlib(void) | |
| 4709 4855 |  | 
| 4710 4856 | 
             
                id_level = rb_intern("level");
         | 
| 4711 4857 | 
             
                id_strategy = rb_intern("strategy");
         | 
| 4858 | 
            +
                id_buffer = rb_intern("buffer");
         | 
| 4712 4859 | 
             
            #endif /* GZIP_SUPPORT */
         | 
| 4713 4860 | 
             
            }
         | 
| 4714 4861 |  | 
| @@ -4829,5 +4976,3 @@ Init_zlib(void) | |
| 4829 4976 | 
             
             * Raised when the data length recorded in the gzip file footer is not equivalent
         | 
| 4830 4977 | 
             
             * to the length of the actual uncompressed data.
         | 
| 4831 4978 | 
             
             */
         | 
| 4832 | 
            -
             | 
| 4833 | 
            -
             |