zlib 0.1.0 → 2.1.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.
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 "0.6.0"
28
+ #define RUBY_ZLIB_VERSION "2.1.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
- static ID id_dictionaries;
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
 
@@ -85,6 +92,7 @@ static void zstream_passthrough_input(struct zstream*);
85
92
  static VALUE zstream_detach_input(struct zstream*);
86
93
  static void zstream_reset(struct zstream*);
87
94
  static VALUE zstream_end(struct zstream*);
95
+ static VALUE zstream_ensure_end(VALUE v);
88
96
  static void zstream_run(struct zstream*, Bytef*, long, int);
89
97
  static VALUE zstream_sync(struct zstream*, Bytef*, long);
90
98
  static void zstream_mark(void*);
@@ -125,7 +133,7 @@ static VALUE rb_inflate_s_allocate(VALUE);
125
133
  static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
126
134
  static VALUE rb_inflate_s_inflate(VALUE, VALUE);
127
135
  static void do_inflate(struct zstream*, VALUE);
128
- static VALUE rb_inflate_inflate(VALUE, VALUE);
136
+ static VALUE rb_inflate_inflate(int, VALUE*, VALUE);
129
137
  static VALUE rb_inflate_addstr(VALUE, VALUE);
130
138
  static VALUE rb_inflate_sync(VALUE, VALUE);
131
139
  static VALUE rb_inflate_sync_point_p(VALUE);
@@ -140,19 +148,19 @@ static void gzfile_reset(struct gzfile*);
140
148
  static void gzfile_close(struct gzfile*, int);
141
149
  static void gzfile_write_raw(struct gzfile*);
142
150
  static VALUE gzfile_read_raw_partial(VALUE);
143
- static VALUE gzfile_read_raw_rescue(VALUE);
144
- static VALUE gzfile_read_raw(struct gzfile*);
145
- 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);
146
154
  static char *gzfile_read_raw_until_zero(struct gzfile*, long);
147
155
  static unsigned int gzfile_get16(const unsigned char*);
148
156
  static unsigned long gzfile_get32(const unsigned char*);
149
157
  static void gzfile_set32(unsigned long n, unsigned char*);
150
158
  static void gzfile_make_header(struct gzfile*);
151
159
  static void gzfile_make_footer(struct gzfile*);
152
- static void gzfile_read_header(struct gzfile*);
153
- 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);
154
162
  static void gzfile_write(struct gzfile*, Bytef*, long);
155
- static long gzfile_read_more(struct gzfile*);
163
+ static long gzfile_read_more(struct gzfile*, VALUE outbuf);
156
164
  static void gzfile_calc_crc(struct gzfile*, VALUE);
157
165
  static VALUE gzfile_read(struct gzfile*, long);
158
166
  static VALUE gzfile_read_all(struct gzfile*);
@@ -197,7 +205,7 @@ static VALUE rb_gzwriter_s_allocate(VALUE);
197
205
  static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
198
206
  static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
199
207
  static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
200
- static VALUE rb_gzwriter_write(VALUE, VALUE);
208
+ static VALUE rb_gzwriter_write(int, VALUE*, VALUE);
201
209
  static VALUE rb_gzwriter_putc(VALUE, VALUE);
202
210
 
203
211
  static VALUE rb_gzreader_s_allocate(VALUE);
@@ -346,7 +354,9 @@ raise_zlib_error(int err, const char *msg)
346
354
  static void
347
355
  finalizer_warn(const char *msg)
348
356
  {
357
+ #if 0
349
358
  fprintf(stderr, "zlib(finalizer): %s\n", msg);
359
+ #endif
350
360
  }
351
361
 
352
362
 
@@ -360,11 +370,7 @@ finalizer_warn(const char *msg)
360
370
  static VALUE
361
371
  rb_zlib_version(VALUE klass)
362
372
  {
363
- VALUE str;
364
-
365
- str = rb_str_new2(zlibVersion());
366
- OBJ_TAINT(str); /* for safe */
367
- return str;
373
+ return rb_str_new2(zlibVersion());
368
374
  }
369
375
 
370
376
  #if SIZEOF_LONG > SIZEOF_INT
@@ -406,6 +412,15 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
406
412
  if (NIL_P(str)) {
407
413
  sum = func(sum, Z_NULL, 0);
408
414
  }
415
+ else if (rb_obj_is_kind_of(str, rb_cIO)) {
416
+ VALUE buf;
417
+ VALUE buflen = INT2NUM(8192);
418
+
419
+ while (!NIL_P(buf = rb_funcall(str, id_read, 1, buflen))) {
420
+ StringValue(buf);
421
+ sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(buf), RSTRING_LEN(buf));
422
+ }
423
+ }
409
424
  else {
410
425
  StringValue(str);
411
426
  sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
@@ -421,6 +436,8 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
421
436
  * Calculates Adler-32 checksum for +string+, and returns updated value of
422
437
  * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
423
438
  * +adler+ is omitted, it assumes that the initial value is given to +adler+.
439
+ * If +string+ is an IO instance, reads from the IO until the IO returns nil
440
+ * and returns Adler-32 of all read data.
424
441
  *
425
442
  * Example usage:
426
443
  *
@@ -451,7 +468,7 @@ rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
451
468
  static VALUE
452
469
  rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
453
470
  {
454
- return ULONG2NUM(
471
+ return ULONG2NUM(
455
472
  adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
456
473
  }
457
474
  #else
@@ -465,7 +482,9 @@ rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
465
482
  *
466
483
  * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
467
484
  * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
468
- * assumes that the initial value is given to +crc+.
485
+ * assumes that the initial value is given to +crc+. If +string+ is an IO instance,
486
+ * reads from the IO until the IO returns nil and returns CRC checksum of all read
487
+ * data.
469
488
  *
470
489
  * FIXME: expression.
471
490
  */
@@ -489,7 +508,7 @@ rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
489
508
  static VALUE
490
509
  rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
491
510
  {
492
- return ULONG2NUM(
511
+ return ULONG2NUM(
493
512
  crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
494
513
  }
495
514
  #else
@@ -529,6 +548,7 @@ struct zstream {
529
548
  unsigned long flags;
530
549
  VALUE buf;
531
550
  VALUE input;
551
+ VALUE mutex;
532
552
  z_stream stream;
533
553
  const struct zstream_funcs {
534
554
  int (*reset)(z_streamp);
@@ -543,7 +563,8 @@ struct zstream {
543
563
  #define ZSTREAM_FLAG_CLOSING 0x8
544
564
  #define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for
545
565
  gzip*/
546
- #define ZSTREAM_FLAG_UNUSED 0x20
566
+ #define ZSTREAM_REUSE_BUFFER 0x20
567
+ #define ZSTREAM_FLAG_UNUSED 0x40
547
568
 
548
569
  #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
549
570
  #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
@@ -552,6 +573,8 @@ struct zstream {
552
573
  #define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE)
553
574
  #define ZSTREAM_BUF_FILLED(z) (NIL_P((z)->buf) ? 0 : RSTRING_LEN((z)->buf))
554
575
 
576
+ #define ZSTREAM_REUSE_BUFFER_P(z) ((z)->flags & ZSTREAM_REUSE_BUFFER)
577
+
555
578
  #define ZSTREAM_EXPAND_BUFFER_OK 0
556
579
 
557
580
  /* I think that more better value should be found,
@@ -601,6 +624,7 @@ zstream_init(struct zstream *z, const struct zstream_funcs *func)
601
624
  z->flags = 0;
602
625
  z->buf = Qnil;
603
626
  z->input = Qnil;
627
+ z->mutex = rb_mutex_new();
604
628
  z->stream.zalloc = zlib_mem_alloc;
605
629
  z->stream.zfree = zlib_mem_free;
606
630
  z->stream.opaque = Z_NULL;
@@ -627,14 +651,22 @@ zstream_expand_buffer(struct zstream *z)
627
651
  long buf_filled = ZSTREAM_BUF_FILLED(z);
628
652
  if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
629
653
  int state = 0;
630
- VALUE self = (VALUE)z->stream.opaque;
631
654
 
632
- rb_obj_reveal(z->buf, rb_cString);
633
- OBJ_INFECT(z->buf, self);
655
+ if (!ZSTREAM_REUSE_BUFFER_P(z)) {
656
+ rb_obj_reveal(z->buf, rb_cString);
657
+ }
634
658
 
659
+ rb_mutex_unlock(z->mutex);
635
660
  rb_protect(rb_yield, z->buf, &state);
636
-
637
- z->buf = Qnil;
661
+ rb_mutex_lock(z->mutex);
662
+
663
+ if (ZSTREAM_REUSE_BUFFER_P(z)) {
664
+ rb_str_modify(z->buf);
665
+ rb_str_set_len(z->buf, 0);
666
+ }
667
+ else {
668
+ z->buf = Qnil;
669
+ }
638
670
  zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
639
671
 
640
672
  if (state)
@@ -644,7 +676,7 @@ zstream_expand_buffer(struct zstream *z)
644
676
  }
645
677
  else {
646
678
  zstream_expand_buffer_into(z,
647
- ZSTREAM_AVAIL_OUT_STEP_MAX - buf_filled);
679
+ ZSTREAM_AVAIL_OUT_STEP_MAX - buf_filled);
648
680
  }
649
681
  }
650
682
  else {
@@ -738,7 +770,7 @@ zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
738
770
  static VALUE
739
771
  zstream_detach_buffer(struct zstream *z)
740
772
  {
741
- VALUE dst, self = (VALUE)z->stream.opaque;
773
+ VALUE dst;
742
774
 
743
775
  if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
744
776
  rb_block_given_p()) {
@@ -752,11 +784,11 @@ zstream_detach_buffer(struct zstream *z)
752
784
  }
753
785
  else {
754
786
  dst = z->buf;
755
- rb_obj_reveal(dst, rb_cString);
787
+ if (!ZSTREAM_REUSE_BUFFER_P(z)) {
788
+ rb_obj_reveal(dst, rb_cString);
789
+ }
756
790
  }
757
791
 
758
- OBJ_INFECT(dst, self);
759
-
760
792
  z->buf = Qnil;
761
793
  z->stream.next_out = 0;
762
794
  z->stream.avail_out = 0;
@@ -845,19 +877,50 @@ zstream_append_input(struct zstream *z, const Bytef *src, long len)
845
877
  static void
846
878
  zstream_discard_input(struct zstream *z, long len)
847
879
  {
848
- if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) {
849
- z->input = Qnil;
880
+ if (NIL_P(z->input)) {
850
881
  }
851
- else {
852
- z->input = rb_str_substr(z->input, len,
853
- RSTRING_LEN(z->input) - len);
882
+ else if (RBASIC_CLASS(z->input) == 0) {
883
+ /* hidden, we created z->input and have complete control */
884
+ char *ptr;
885
+ long oldlen, newlen;
886
+
887
+ RSTRING_GETMEM(z->input, ptr, oldlen);
888
+ newlen = oldlen - len;
889
+ if (newlen > 0) {
890
+ memmove(ptr, ptr + len, newlen);
891
+ }
892
+ if (newlen < 0) {
893
+ newlen = 0;
894
+ }
895
+ rb_str_resize(z->input, newlen);
896
+ if (newlen == 0) {
897
+ rb_gc_force_recycle(z->input);
898
+ z->input = Qnil;
899
+ }
900
+ else {
901
+ rb_str_set_len(z->input, newlen);
902
+ }
903
+ }
904
+ else { /* do not mangle user-provided data */
905
+ if (RSTRING_LEN(z->input) <= len) {
906
+ z->input = Qnil;
907
+ }
908
+ else {
909
+ z->input = rb_str_substr(z->input, len,
910
+ RSTRING_LEN(z->input) - len);
911
+ }
854
912
  }
855
913
  }
856
914
 
857
915
  static void
858
916
  zstream_reset_input(struct zstream *z)
859
917
  {
860
- z->input = Qnil;
918
+ if (!NIL_P(z->input) && RBASIC_CLASS(z->input) == 0) {
919
+ rb_str_resize(z->input, 0);
920
+ }
921
+ else {
922
+ z->input = Qnil;
923
+ }
861
924
  }
862
925
 
863
926
  static void
@@ -882,7 +945,6 @@ zstream_detach_input(struct zstream *z)
882
945
  rb_obj_reveal(dst, rb_cString);
883
946
  }
884
947
  z->input = Qnil;
885
- rb_obj_reveal(dst, rb_cString);
886
948
  return dst;
887
949
  }
888
950
 
@@ -925,6 +987,12 @@ zstream_end(struct zstream *z)
925
987
  return Qnil;
926
988
  }
927
989
 
990
+ static VALUE
991
+ zstream_ensure_end(VALUE v)
992
+ {
993
+ return zstream_end((struct zstream *)v);
994
+ }
995
+
928
996
  static void *
929
997
  zstream_run_func(void *ptr)
930
998
  {
@@ -981,6 +1049,7 @@ zstream_run_func(void *ptr)
981
1049
 
982
1050
  /*
983
1051
  * There is no safe way to interrupt z->run->func().
1052
+ * async-signal-safe
984
1053
  */
985
1054
  static void
986
1055
  zstream_unblock_func(void *ptr)
@@ -991,11 +1060,11 @@ zstream_unblock_func(void *ptr)
991
1060
  }
992
1061
 
993
1062
  static void
994
- zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1063
+ zstream_run0(struct zstream *z, Bytef *src, long len, int flush)
995
1064
  {
996
1065
  struct zstream_run_args args;
997
1066
  int err;
998
- VALUE guard = Qnil;
1067
+ VALUE old_input = Qnil;
999
1068
 
1000
1069
  args.z = z;
1001
1070
  args.flush = flush;
@@ -1009,12 +1078,13 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1009
1078
  }
1010
1079
  else {
1011
1080
  zstream_append_input(z, src, len);
1012
- z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1013
- z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1014
1081
  /* keep reference to `z->input' so as not to be garbage collected
1015
1082
  after zstream_reset_input() and prevent `z->stream.next_in'
1016
1083
  from dangling. */
1017
- guard = z->input;
1084
+ old_input = zstream_detach_input(z);
1085
+ rb_obj_hide(old_input); /* for GVL release and later recycle */
1086
+ z->stream.next_in = (Bytef*)RSTRING_PTR(old_input);
1087
+ z->stream.avail_in = MAX_UINT(RSTRING_LEN(old_input));
1018
1088
  }
1019
1089
 
1020
1090
  if (z->stream.avail_out == 0) {
@@ -1022,8 +1092,20 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1022
1092
  }
1023
1093
 
1024
1094
  loop:
1095
+ #ifndef RB_NOGVL_UBF_ASYNC_SAFE
1025
1096
  err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
1026
1097
  zstream_unblock_func, (void *)&args);
1098
+ #else
1099
+ err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
1100
+ zstream_unblock_func, (void *)&args,
1101
+ RB_NOGVL_UBF_ASYNC_SAFE);
1102
+ #endif
1103
+
1104
+ /* retry if no exception is thrown */
1105
+ if (err == Z_OK && args.interrupt) {
1106
+ args.interrupt = 0;
1107
+ goto loop;
1108
+ }
1027
1109
 
1028
1110
  if (flush != Z_FINISH && err == Z_BUF_ERROR
1029
1111
  && z->stream.avail_out > 0) {
@@ -1052,13 +1134,42 @@ loop:
1052
1134
 
1053
1135
  if (z->stream.avail_in > 0) {
1054
1136
  zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1055
- RB_GC_GUARD(guard); /* prevent tail call to make guard effective */
1137
+ }
1138
+ if (!NIL_P(old_input)) {
1139
+ rb_str_resize(old_input, 0);
1140
+ rb_gc_force_recycle(old_input);
1056
1141
  }
1057
1142
 
1058
1143
  if (args.jump_state)
1059
1144
  rb_jump_tag(args.jump_state);
1060
1145
  }
1061
1146
 
1147
+ struct zstream_run_synchronized_args {
1148
+ struct zstream *z;
1149
+ Bytef *src;
1150
+ long len;
1151
+ int flush;
1152
+ };
1153
+
1154
+ static VALUE
1155
+ zstream_run_synchronized(VALUE value_arg)
1156
+ {
1157
+ struct zstream_run_synchronized_args *run_args = (struct zstream_run_synchronized_args *)value_arg;
1158
+ zstream_run0(run_args->z, run_args->src, run_args->len, run_args->flush);
1159
+ return Qnil;
1160
+ }
1161
+
1162
+ static void
1163
+ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1164
+ {
1165
+ struct zstream_run_synchronized_args run_args;
1166
+ run_args.z = z;
1167
+ run_args.src = src;
1168
+ run_args.len = len;
1169
+ run_args.flush = flush;
1170
+ rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&run_args);
1171
+ }
1172
+
1062
1173
  static VALUE
1063
1174
  zstream_sync(struct zstream *z, Bytef *src, long len)
1064
1175
  {
@@ -1104,6 +1215,7 @@ zstream_mark(void *p)
1104
1215
  struct zstream *z = p;
1105
1216
  rb_gc_mark(z->buf);
1106
1217
  rb_gc_mark(z->input);
1218
+ rb_gc_mark(z->mutex);
1107
1219
  }
1108
1220
 
1109
1221
  static void
@@ -1285,7 +1397,6 @@ rb_zstream_flush_next_in(VALUE obj)
1285
1397
 
1286
1398
  TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1287
1399
  dst = zstream_detach_input(z);
1288
- OBJ_INFECT(dst, obj);
1289
1400
  return dst;
1290
1401
  }
1291
1402
 
@@ -1381,7 +1492,7 @@ rb_zstream_data_type(VALUE obj)
1381
1492
  static VALUE
1382
1493
  rb_zstream_adler(VALUE obj)
1383
1494
  {
1384
- return rb_uint2inum(get_zstream(obj)->stream.adler);
1495
+ return rb_uint2inum(get_zstream(obj)->stream.adler);
1385
1496
  }
1386
1497
 
1387
1498
  /*
@@ -1604,9 +1715,8 @@ rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass)
1604
1715
 
1605
1716
  args[0] = (VALUE)&z;
1606
1717
  args[1] = src;
1607
- dst = rb_ensure(deflate_run, (VALUE)args, zstream_end, (VALUE)&z);
1718
+ dst = rb_ensure(deflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
1608
1719
 
1609
- OBJ_INFECT(dst, src);
1610
1720
  return dst;
1611
1721
  }
1612
1722
 
@@ -1656,7 +1766,6 @@ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
1656
1766
  VALUE src, flush;
1657
1767
 
1658
1768
  rb_scan_args(argc, argv, "11", &src, &flush);
1659
- OBJ_INFECT(obj, src);
1660
1769
  do_deflate(z, src, ARG_FLUSH(flush));
1661
1770
 
1662
1771
  return zstream_detach_buffer(z);
@@ -1674,7 +1783,6 @@ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
1674
1783
  static VALUE
1675
1784
  rb_deflate_addstr(VALUE obj, VALUE src)
1676
1785
  {
1677
- OBJ_INFECT(obj, src);
1678
1786
  do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
1679
1787
  return obj;
1680
1788
  }
@@ -1774,7 +1882,6 @@ rb_deflate_set_dictionary(VALUE obj, VALUE dic)
1774
1882
  VALUE src = dic;
1775
1883
  int err;
1776
1884
 
1777
- OBJ_INFECT(obj, dic);
1778
1885
  StringValue(src);
1779
1886
  err = deflateSetDictionary(&z->stream,
1780
1887
  (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
@@ -1919,9 +2026,8 @@ rb_inflate_s_inflate(VALUE obj, VALUE src)
1919
2026
 
1920
2027
  args[0] = (VALUE)&z;
1921
2028
  args[1] = src;
1922
- dst = rb_ensure(inflate_run, (VALUE)args, zstream_end, (VALUE)&z);
2029
+ dst = rb_ensure(inflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
1923
2030
 
1924
- OBJ_INFECT(dst, src);
1925
2031
  return dst;
1926
2032
  }
1927
2033
 
@@ -1962,8 +2068,8 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
1962
2068
  * Document-method: Zlib::Inflate#inflate
1963
2069
  *
1964
2070
  * call-seq:
1965
- * inflate(deflate_string) -> String
1966
- * inflate(deflate_string) { |chunk| ... } -> nil
2071
+ * inflate(deflate_string, buffer: nil) -> String
2072
+ * inflate(deflate_string, buffer: nil) { |chunk| ... } -> nil
1967
2073
  *
1968
2074
  * Inputs +deflate_string+ into the inflate stream and returns the output from
1969
2075
  * the stream. Calling this method, both the input and the output buffer of
@@ -1973,6 +2079,15 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
1973
2079
  * If a block is given consecutive inflated chunks from the +deflate_string+
1974
2080
  * are yielded to the block and +nil+ is returned.
1975
2081
  *
2082
+ * If a :buffer keyword argument is given and not nil:
2083
+ *
2084
+ * * The :buffer keyword should be a String, and will used as the output buffer.
2085
+ * Using this option can reuse the memory required during inflation.
2086
+ * * When not passing a block, the return value will be the same object as the
2087
+ * :buffer keyword argument.
2088
+ * * When passing a block, the yielded chunks will be the same value as the
2089
+ * :buffer keyword argument.
2090
+ *
1976
2091
  * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
1977
2092
  * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
1978
2093
  * call this method again with an empty string to flush the stream:
@@ -1996,12 +2111,37 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
1996
2111
  * See also Zlib::Inflate.new
1997
2112
  */
1998
2113
  static VALUE
1999
- rb_inflate_inflate(VALUE obj, VALUE src)
2114
+ rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
2000
2115
  {
2001
2116
  struct zstream *z = get_zstream(obj);
2002
- VALUE dst;
2117
+ VALUE dst, src, opts, buffer = Qnil;
2003
2118
 
2004
- OBJ_INFECT(obj, src);
2119
+ if (OPTHASH_GIVEN_P(opts)) {
2120
+ VALUE buf;
2121
+ rb_get_kwargs(opts, &id_buffer, 0, 1, &buf);
2122
+ if (buf != Qundef && buf != Qnil) {
2123
+ buffer = StringValue(buf);
2124
+ }
2125
+ }
2126
+ if (buffer != Qnil) {
2127
+ if (!(ZSTREAM_REUSE_BUFFER_P(z) && z->buf == buffer)) {
2128
+ long len = RSTRING_LEN(buffer);
2129
+ if (len >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
2130
+ rb_str_modify(buffer);
2131
+ }
2132
+ else {
2133
+ len = ZSTREAM_AVAIL_OUT_STEP_MAX - len;
2134
+ rb_str_modify_expand(buffer, len);
2135
+ }
2136
+ rb_str_set_len(buffer, 0);
2137
+ z->flags |= ZSTREAM_REUSE_BUFFER;
2138
+ z->buf = buffer;
2139
+ }
2140
+ } else if (ZSTREAM_REUSE_BUFFER_P(z)) {
2141
+ z->flags &= ~ZSTREAM_REUSE_BUFFER;
2142
+ z->buf = Qnil;
2143
+ }
2144
+ rb_scan_args(argc, argv, "10", &src);
2005
2145
 
2006
2146
  if (ZSTREAM_IS_FINISHED(z)) {
2007
2147
  if (NIL_P(src)) {
@@ -2010,8 +2150,11 @@ rb_inflate_inflate(VALUE obj, VALUE src)
2010
2150
  else {
2011
2151
  StringValue(src);
2012
2152
  zstream_append_buffer2(z, src);
2013
- dst = rb_str_new(0, 0);
2014
- OBJ_INFECT(dst, obj);
2153
+ if (ZSTREAM_REUSE_BUFFER_P(z)) {
2154
+ dst = rb_str_resize(buffer, 0);
2155
+ } else {
2156
+ dst = rb_str_new(0, 0);
2157
+ }
2015
2158
  }
2016
2159
  }
2017
2160
  else {
@@ -2037,8 +2180,6 @@ rb_inflate_addstr(VALUE obj, VALUE src)
2037
2180
  {
2038
2181
  struct zstream *z = get_zstream(obj);
2039
2182
 
2040
- OBJ_INFECT(obj, src);
2041
-
2042
2183
  if (ZSTREAM_IS_FINISHED(z)) {
2043
2184
  if (!NIL_P(src)) {
2044
2185
  StringValue(src);
@@ -2068,7 +2209,6 @@ rb_inflate_sync(VALUE obj, VALUE src)
2068
2209
  {
2069
2210
  struct zstream *z = get_zstream(obj);
2070
2211
 
2071
- OBJ_INFECT(obj, src);
2072
2212
  StringValue(src);
2073
2213
  return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
2074
2214
  }
@@ -2110,7 +2250,6 @@ rb_inflate_set_dictionary(VALUE obj, VALUE dic)
2110
2250
  VALUE src = dic;
2111
2251
  int err;
2112
2252
 
2113
- OBJ_INFECT(obj, dic);
2114
2253
  StringValue(src);
2115
2254
  err = inflateSetDictionary(&z->stream,
2116
2255
  (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
@@ -2167,7 +2306,7 @@ rb_inflate_set_dictionary(VALUE obj, VALUE dic)
2167
2306
  #define OS_CODE OS_UNIX
2168
2307
  #endif
2169
2308
 
2170
- static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
2309
+ static ID id_write, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
2171
2310
  static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
2172
2311
 
2173
2312
 
@@ -2191,7 +2330,6 @@ struct gzfile {
2191
2330
  rb_encoding *enc2;
2192
2331
  rb_econv_t *ec;
2193
2332
  VALUE ecopts;
2194
- char *cbuf;
2195
2333
  VALUE path;
2196
2334
  };
2197
2335
  #define GZFILE_CBUF_CAPA 10
@@ -2199,12 +2337,23 @@ struct gzfile {
2199
2337
  #define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
2200
2338
  #define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
2201
2339
  #define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2)
2340
+ #define GZFILE_FLAG_MTIME_IS_SET (ZSTREAM_FLAG_UNUSED << 3)
2202
2341
 
2203
2342
  #define GZFILE_IS_FINISHED(gz) \
2204
2343
  (ZSTREAM_IS_FINISHED(&(gz)->z) && ZSTREAM_BUF_FILLED(&(gz)->z) == 0)
2205
2344
 
2206
2345
  #define GZFILE_READ_SIZE 2048
2207
2346
 
2347
+ struct read_raw_arg {
2348
+ VALUE io;
2349
+ union {
2350
+ const VALUE argv[2]; /* for rb_funcallv */
2351
+ struct {
2352
+ VALUE len;
2353
+ VALUE buf;
2354
+ } in;
2355
+ } as;
2356
+ };
2208
2357
 
2209
2358
  static void
2210
2359
  gzfile_mark(void *p)
@@ -2231,22 +2380,13 @@ gzfile_free(void *p)
2231
2380
  }
2232
2381
  zstream_finalize(z);
2233
2382
  }
2234
- if (gz->cbuf) {
2235
- xfree(gz->cbuf);
2236
- }
2237
2383
  xfree(gz);
2238
2384
  }
2239
2385
 
2240
2386
  static size_t
2241
2387
  gzfile_memsize(const void *p)
2242
2388
  {
2243
- const struct gzfile *gz = p;
2244
- size_t size = sizeof(struct gzfile);
2245
-
2246
- if (gz->cbuf)
2247
- size += GZFILE_CBUF_CAPA;
2248
-
2249
- return size;
2389
+ return sizeof(struct gzfile);
2250
2390
  }
2251
2391
 
2252
2392
  static const rb_data_type_t gzfile_data_type = {
@@ -2275,7 +2415,6 @@ gzfile_init(struct gzfile *gz, const struct zstream_funcs *funcs, void (*endfunc
2275
2415
  gz->ec = NULL;
2276
2416
  gz->ecflags = 0;
2277
2417
  gz->ecopts = Qnil;
2278
- gz->cbuf = 0;
2279
2418
  gz->path = Qnil;
2280
2419
  }
2281
2420
 
@@ -2329,7 +2468,6 @@ gzfile_write_raw(struct gzfile *gz)
2329
2468
 
2330
2469
  if (ZSTREAM_BUF_FILLED(&gz->z) > 0) {
2331
2470
  str = zstream_detach_buffer(&gz->z);
2332
- OBJ_TAINT(str); /* for safe */
2333
2471
  rb_funcall(gz->io, id_write, 1, str);
2334
2472
  if ((gz->z.flags & GZFILE_FLAG_SYNC)
2335
2473
  && rb_respond_to(gz->io, id_flush))
@@ -2340,21 +2478,23 @@ gzfile_write_raw(struct gzfile *gz)
2340
2478
  static VALUE
2341
2479
  gzfile_read_raw_partial(VALUE arg)
2342
2480
  {
2343
- struct gzfile *gz = (struct gzfile*)arg;
2481
+ struct read_raw_arg *ra = (struct read_raw_arg *)arg;
2344
2482
  VALUE str;
2483
+ int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
2345
2484
 
2346
- str = rb_funcall(gz->io, id_readpartial, 1, INT2FIX(GZFILE_READ_SIZE));
2485
+ str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv);
2347
2486
  Check_Type(str, T_STRING);
2348
2487
  return str;
2349
2488
  }
2350
2489
 
2351
2490
  static VALUE
2352
- gzfile_read_raw_rescue(VALUE arg)
2491
+ gzfile_read_raw_rescue(VALUE arg, VALUE _)
2353
2492
  {
2354
- struct gzfile *gz = (struct gzfile*)arg;
2493
+ struct read_raw_arg *ra = (struct read_raw_arg *)arg;
2355
2494
  VALUE str = Qnil;
2356
2495
  if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
2357
- str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
2496
+ int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
2497
+ str = rb_funcallv(ra->io, id_read, argc, ra->as.argv);
2358
2498
  if (!NIL_P(str)) {
2359
2499
  Check_Type(str, T_STRING);
2360
2500
  }
@@ -2363,15 +2503,21 @@ gzfile_read_raw_rescue(VALUE arg)
2363
2503
  }
2364
2504
 
2365
2505
  static VALUE
2366
- gzfile_read_raw(struct gzfile *gz)
2506
+ gzfile_read_raw(struct gzfile *gz, VALUE outbuf)
2367
2507
  {
2368
- return rb_rescue2(gzfile_read_raw_partial, (VALUE)gz,
2369
- gzfile_read_raw_rescue, (VALUE)gz,
2508
+ struct read_raw_arg ra;
2509
+
2510
+ ra.io = gz->io;
2511
+ ra.as.in.len = INT2FIX(GZFILE_READ_SIZE);
2512
+ ra.as.in.buf = outbuf;
2513
+
2514
+ return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
2515
+ gzfile_read_raw_rescue, (VALUE)&ra,
2370
2516
  rb_eEOFError, rb_eNoMethodError, (VALUE)0);
2371
2517
  }
2372
2518
 
2373
2519
  static int
2374
- gzfile_read_raw_ensure(struct gzfile *gz, long size)
2520
+ gzfile_read_raw_ensure(struct gzfile *gz, long size, VALUE outbuf)
2375
2521
  {
2376
2522
  VALUE str;
2377
2523
 
@@ -2380,7 +2526,7 @@ gzfile_read_raw_ensure(struct gzfile *gz, long size)
2380
2526
  rb_raise(cGzError, "unexpected end of string");
2381
2527
  }
2382
2528
  while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
2383
- str = gzfile_read_raw(gz);
2529
+ str = gzfile_read_raw(gz, outbuf);
2384
2530
  if (NIL_P(str)) return 0;
2385
2531
  zstream_append_input2(&gz->z, str);
2386
2532
  }
@@ -2397,7 +2543,7 @@ gzfile_read_raw_until_zero(struct gzfile *gz, long offset)
2397
2543
  p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
2398
2544
  RSTRING_LEN(gz->z.input) - offset);
2399
2545
  if (p) break;
2400
- str = gzfile_read_raw(gz);
2546
+ str = gzfile_read_raw(gz, Qnil);
2401
2547
  if (NIL_P(str)) {
2402
2548
  rb_raise(cGzError, "unexpected end of file");
2403
2549
  }
@@ -2478,7 +2624,7 @@ gzfile_make_header(struct gzfile *gz)
2478
2624
  if (!NIL_P(gz->comment)) {
2479
2625
  flags |= GZ_FLAG_COMMENT;
2480
2626
  }
2481
- if (gz->mtime == 0) {
2627
+ if (!(gz->z.flags & GZFILE_FLAG_MTIME_IS_SET)) {
2482
2628
  gz->mtime = time(0);
2483
2629
  }
2484
2630
 
@@ -2522,13 +2668,14 @@ gzfile_make_footer(struct gzfile *gz)
2522
2668
  }
2523
2669
 
2524
2670
  static void
2525
- gzfile_read_header(struct gzfile *gz)
2671
+ gzfile_read_header(struct gzfile *gz, VALUE outbuf)
2526
2672
  {
2527
2673
  const unsigned char *head;
2528
2674
  long len;
2529
2675
  char flags, *p;
2530
2676
 
2531
- if (!gzfile_read_raw_ensure(gz, 10)) { /* 10 is the size of gzip header */
2677
+ /* 10 is the size of gzip header */
2678
+ if (!gzfile_read_raw_ensure(gz, 10, outbuf)) {
2532
2679
  gzfile_raise(gz, cGzError, "not in gzip format");
2533
2680
  }
2534
2681
 
@@ -2567,33 +2714,31 @@ gzfile_read_header(struct gzfile *gz)
2567
2714
  zstream_discard_input(&gz->z, 10);
2568
2715
 
2569
2716
  if (flags & GZ_FLAG_EXTRA) {
2570
- if (!gzfile_read_raw_ensure(gz, 2)) {
2717
+ if (!gzfile_read_raw_ensure(gz, 2, outbuf)) {
2571
2718
  rb_raise(cGzError, "unexpected end of file");
2572
2719
  }
2573
2720
  len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
2574
- if (!gzfile_read_raw_ensure(gz, 2 + len)) {
2721
+ if (!gzfile_read_raw_ensure(gz, 2 + len, outbuf)) {
2575
2722
  rb_raise(cGzError, "unexpected end of file");
2576
2723
  }
2577
2724
  zstream_discard_input(&gz->z, 2 + len);
2578
2725
  }
2579
2726
  if (flags & GZ_FLAG_ORIG_NAME) {
2580
- if (!gzfile_read_raw_ensure(gz, 1)) {
2727
+ if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
2581
2728
  rb_raise(cGzError, "unexpected end of file");
2582
2729
  }
2583
2730
  p = gzfile_read_raw_until_zero(gz, 0);
2584
2731
  len = p - RSTRING_PTR(gz->z.input);
2585
2732
  gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len);
2586
- OBJ_TAINT(gz->orig_name); /* for safe */
2587
2733
  zstream_discard_input(&gz->z, len + 1);
2588
2734
  }
2589
2735
  if (flags & GZ_FLAG_COMMENT) {
2590
- if (!gzfile_read_raw_ensure(gz, 1)) {
2736
+ if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
2591
2737
  rb_raise(cGzError, "unexpected end of file");
2592
2738
  }
2593
2739
  p = gzfile_read_raw_until_zero(gz, 0);
2594
2740
  len = p - RSTRING_PTR(gz->z.input);
2595
2741
  gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
2596
- OBJ_TAINT(gz->comment); /* for safe */
2597
2742
  zstream_discard_input(&gz->z, len + 1);
2598
2743
  }
2599
2744
 
@@ -2603,13 +2748,14 @@ gzfile_read_header(struct gzfile *gz)
2603
2748
  }
2604
2749
 
2605
2750
  static void
2606
- gzfile_check_footer(struct gzfile *gz)
2751
+ gzfile_check_footer(struct gzfile *gz, VALUE outbuf)
2607
2752
  {
2608
2753
  unsigned long crc, length;
2609
2754
 
2610
2755
  gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
2611
2756
 
2612
- if (!gzfile_read_raw_ensure(gz, 8)) { /* 8 is the size of gzip footer */
2757
+ /* 8 is the size of gzip footer */
2758
+ if (!gzfile_read_raw_ensure(gz, 8, outbuf)) {
2613
2759
  gzfile_raise(gz, cNoFooter, "footer is not found");
2614
2760
  }
2615
2761
 
@@ -2643,12 +2789,12 @@ gzfile_write(struct gzfile *gz, Bytef *str, long len)
2643
2789
  }
2644
2790
 
2645
2791
  static long
2646
- gzfile_read_more(struct gzfile *gz)
2792
+ gzfile_read_more(struct gzfile *gz, VALUE outbuf)
2647
2793
  {
2648
2794
  VALUE str;
2649
2795
 
2650
2796
  while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2651
- str = gzfile_read_raw(gz);
2797
+ str = gzfile_read_raw(gz, outbuf);
2652
2798
  if (NIL_P(str)) {
2653
2799
  if (!ZSTREAM_IS_FINISHED(&gz->z)) {
2654
2800
  rb_raise(cGzError, "unexpected end of file");
@@ -2673,7 +2819,7 @@ gzfile_calc_crc(struct gzfile *gz, VALUE str)
2673
2819
  }
2674
2820
  else {
2675
2821
  gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
2676
- RSTRING_LEN(str) - gz->ungetc);
2822
+ RSTRING_LEN(str) - gz->ungetc);
2677
2823
  gz->ungetc = 0;
2678
2824
  }
2679
2825
  }
@@ -2683,13 +2829,11 @@ gzfile_newstr(struct gzfile *gz, VALUE str)
2683
2829
  {
2684
2830
  if (!gz->enc2) {
2685
2831
  rb_enc_associate(str, gz->enc);
2686
- OBJ_TAINT(str); /* for safe */
2687
2832
  return str;
2688
2833
  }
2689
2834
  if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2690
2835
  str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
2691
2836
  rb_enc_associate(str, gz->enc);
2692
- OBJ_TAINT(str);
2693
2837
  return str;
2694
2838
  }
2695
2839
  return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
@@ -2704,11 +2848,11 @@ gzfile_fill(struct gzfile *gz, long len)
2704
2848
  if (len == 0)
2705
2849
  return 0;
2706
2850
  while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
2707
- gzfile_read_more(gz);
2851
+ gzfile_read_more(gz, Qnil);
2708
2852
  }
2709
2853
  if (GZFILE_IS_FINISHED(gz)) {
2710
2854
  if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2711
- gzfile_check_footer(gz);
2855
+ gzfile_check_footer(gz, Qnil);
2712
2856
  }
2713
2857
  return -1;
2714
2858
  }
@@ -2736,9 +2880,6 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
2736
2880
  if (len < 0)
2737
2881
  rb_raise(rb_eArgError, "negative length %ld given", len);
2738
2882
 
2739
- if (!NIL_P(outbuf))
2740
- OBJ_TAINT(outbuf);
2741
-
2742
2883
  if (len == 0) {
2743
2884
  if (NIL_P(outbuf))
2744
2885
  return rb_str_new(0, 0);
@@ -2748,11 +2889,11 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
2748
2889
  }
2749
2890
  }
2750
2891
  while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
2751
- gzfile_read_more(gz);
2892
+ gzfile_read_more(gz, outbuf);
2752
2893
  }
2753
2894
  if (GZFILE_IS_FINISHED(gz)) {
2754
2895
  if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2755
- gzfile_check_footer(gz);
2896
+ gzfile_check_footer(gz, outbuf);
2756
2897
  }
2757
2898
  if (!NIL_P(outbuf))
2758
2899
  rb_str_resize(outbuf, 0);
@@ -2765,10 +2906,10 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
2765
2906
  if (!NIL_P(outbuf)) {
2766
2907
  rb_str_resize(outbuf, RSTRING_LEN(dst));
2767
2908
  memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
2768
- RB_GC_GUARD(dst);
2909
+ rb_str_resize(dst, 0);
2910
+ rb_gc_force_recycle(dst);
2769
2911
  dst = outbuf;
2770
2912
  }
2771
- OBJ_TAINT(dst); /* for safe */
2772
2913
  return dst;
2773
2914
  }
2774
2915
 
@@ -2778,11 +2919,11 @@ gzfile_read_all(struct gzfile *gz)
2778
2919
  VALUE dst;
2779
2920
 
2780
2921
  while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2781
- gzfile_read_more(gz);
2922
+ gzfile_read_more(gz, Qnil);
2782
2923
  }
2783
2924
  if (GZFILE_IS_FINISHED(gz)) {
2784
2925
  if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2785
- gzfile_check_footer(gz);
2926
+ gzfile_check_footer(gz, Qnil);
2786
2927
  }
2787
2928
  return rb_str_new(0, 0);
2788
2929
  }
@@ -2790,7 +2931,6 @@ gzfile_read_all(struct gzfile *gz)
2790
2931
  dst = zstream_detach_buffer(&gz->z);
2791
2932
  if (NIL_P(dst)) return dst;
2792
2933
  gzfile_calc_crc(gz, dst);
2793
- OBJ_TAINT(dst);
2794
2934
  return gzfile_newstr(gz, dst);
2795
2935
  }
2796
2936
 
@@ -2802,11 +2942,11 @@ gzfile_getc(struct gzfile *gz)
2802
2942
 
2803
2943
  len = rb_enc_mbmaxlen(gz->enc);
2804
2944
  while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
2805
- gzfile_read_more(gz);
2945
+ gzfile_read_more(gz, Qnil);
2806
2946
  }
2807
2947
  if (GZFILE_IS_FINISHED(gz)) {
2808
2948
  if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2809
- gzfile_check_footer(gz);
2949
+ gzfile_check_footer(gz, Qnil);
2810
2950
  }
2811
2951
  return Qnil;
2812
2952
  }
@@ -2814,22 +2954,18 @@ gzfile_getc(struct gzfile *gz)
2814
2954
  if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2815
2955
  const unsigned char *ss, *sp, *se;
2816
2956
  unsigned char *ds, *dp, *de;
2957
+ VALUE cbuf = rb_enc_str_new(0, GZFILE_CBUF_CAPA, gz->enc);
2817
2958
 
2818
- if (!gz->cbuf) {
2819
- gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA);
2820
- }
2821
2959
  ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
2822
2960
  se = sp + ZSTREAM_BUF_FILLED(&gz->z);
2823
- ds = dp = (unsigned char *)gz->cbuf;
2961
+ ds = dp = (unsigned char *)RSTRING_PTR(cbuf);
2824
2962
  de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
2825
2963
  (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
2826
2964
  rb_econv_check_error(gz->ec);
2827
2965
  dst = zstream_shift_buffer(&gz->z, sp - ss);
2828
2966
  gzfile_calc_crc(gz, dst);
2829
- dst = rb_str_new(gz->cbuf, dp - ds);
2830
- rb_enc_associate(dst, gz->enc);
2831
- OBJ_TAINT(dst);
2832
- return dst;
2967
+ rb_str_resize(cbuf, dp - ds);
2968
+ return cbuf;
2833
2969
  }
2834
2970
  else {
2835
2971
  buf = gz->z.buf;
@@ -2876,7 +3012,7 @@ gzfile_writer_end(struct gzfile *gz)
2876
3012
  if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2877
3013
  gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2878
3014
 
2879
- rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
3015
+ rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
2880
3016
  }
2881
3017
 
2882
3018
  static VALUE
@@ -2886,7 +3022,7 @@ gzfile_reader_end_run(VALUE arg)
2886
3022
 
2887
3023
  if (GZFILE_IS_FINISHED(gz)
2888
3024
  && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2889
- gzfile_check_footer(gz);
3025
+ gzfile_check_footer(gz, Qnil);
2890
3026
  }
2891
3027
 
2892
3028
  return Qnil;
@@ -2898,7 +3034,7 @@ gzfile_reader_end(struct gzfile *gz)
2898
3034
  if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2899
3035
  gz->z.flags |= ZSTREAM_FLAG_CLOSING;
2900
3036
 
2901
- rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
3037
+ rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
2902
3038
  }
2903
3039
 
2904
3040
  static void
@@ -2923,12 +3059,11 @@ gzfile_reader_get_unused(struct gzfile *gz)
2923
3059
  if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
2924
3060
  if (!GZFILE_IS_FINISHED(gz)) return Qnil;
2925
3061
  if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2926
- gzfile_check_footer(gz);
3062
+ gzfile_check_footer(gz, Qnil);
2927
3063
  }
2928
3064
  if (NIL_P(gz->z.input)) return Qnil;
2929
3065
 
2930
3066
  str = rb_str_resurrect(gz->z.input);
2931
- OBJ_TAINT(str); /* for safe */
2932
3067
  return str;
2933
3068
  }
2934
3069
 
@@ -2995,7 +3130,7 @@ static VALUE
2995
3130
  new_wrap(VALUE tmp)
2996
3131
  {
2997
3132
  new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp;
2998
- return rb_class_new_instance(arg->argc, arg->argv, arg->klass);
3133
+ return rb_class_new_instance_kw(arg->argc, arg->argv, arg->klass, RB_PASS_CALLED_KEYWORDS);
2999
3134
  }
3000
3135
 
3001
3136
  static VALUE
@@ -3028,7 +3163,7 @@ gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
3028
3163
  }
3029
3164
  }
3030
3165
  else {
3031
- obj = rb_class_new_instance(argc, argv, klass);
3166
+ obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
3032
3167
  }
3033
3168
 
3034
3169
  if (rb_block_given_p()) {
@@ -3145,7 +3280,6 @@ rb_gzfile_orig_name(VALUE obj)
3145
3280
  if (!NIL_P(str)) {
3146
3281
  str = rb_str_dup(str);
3147
3282
  }
3148
- OBJ_TAINT(str); /* for safe */
3149
3283
  return str;
3150
3284
  }
3151
3285
 
@@ -3162,7 +3296,6 @@ rb_gzfile_comment(VALUE obj)
3162
3296
  if (!NIL_P(str)) {
3163
3297
  str = rb_str_dup(str);
3164
3298
  }
3165
- OBJ_TAINT(str); /* for safe */
3166
3299
  return str;
3167
3300
  }
3168
3301
 
@@ -3221,6 +3354,7 @@ rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
3221
3354
 
3222
3355
  val = rb_Integer(mtime);
3223
3356
  gz->mtime = NUM2UINT(val);
3357
+ gz->z.flags |= GZFILE_FLAG_MTIME_IS_SET;
3224
3358
 
3225
3359
  return mtime;
3226
3360
  }
@@ -3419,6 +3553,16 @@ rb_gzfile_path(VALUE obj)
3419
3553
  return gz->path;
3420
3554
  }
3421
3555
 
3556
+ static VALUE
3557
+ gzfile_initialize_path_partial(VALUE obj)
3558
+ {
3559
+ struct gzfile* gz;
3560
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3561
+ gz->path = rb_funcall(gz->io, id_path, 0);
3562
+ rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3563
+ return Qnil;
3564
+ }
3565
+
3422
3566
  static void
3423
3567
  rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
3424
3568
  {
@@ -3527,8 +3671,8 @@ rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
3527
3671
  rb_gzfile_ecopts(gz, opt);
3528
3672
 
3529
3673
  if (rb_respond_to(io, id_path)) {
3530
- gz->path = rb_funcall(gz->io, id_path, 0);
3531
- rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3674
+ /* File#path may raise IOError in case when a path is unavailable */
3675
+ rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
3532
3676
  }
3533
3677
 
3534
3678
  return obj;
@@ -3566,18 +3710,23 @@ rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
3566
3710
  * Same as IO.
3567
3711
  */
3568
3712
  static VALUE
3569
- rb_gzwriter_write(VALUE obj, VALUE str)
3713
+ rb_gzwriter_write(int argc, VALUE *argv, VALUE obj)
3570
3714
  {
3571
3715
  struct gzfile *gz = get_gzfile(obj);
3572
-
3573
- if (!RB_TYPE_P(str, T_STRING))
3574
- str = rb_obj_as_string(str);
3575
- if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3576
- str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
3716
+ size_t total = 0;
3717
+
3718
+ while (argc-- > 0) {
3719
+ VALUE str = *argv++;
3720
+ if (!RB_TYPE_P(str, T_STRING))
3721
+ str = rb_obj_as_string(str);
3722
+ if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3723
+ str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
3724
+ }
3725
+ gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
3726
+ total += RSTRING_LEN(str);
3727
+ RB_GC_GUARD(str);
3577
3728
  }
3578
- gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
3579
- RB_GC_GUARD(str);
3580
- return INT2FIX(RSTRING_LEN(str));
3729
+ return SIZET2NUM(total);
3581
3730
  }
3582
3731
 
3583
3732
  /*
@@ -3692,6 +3841,60 @@ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
3692
3841
  return gzfile_s_open(argc, argv, klass, "rb");
3693
3842
  }
3694
3843
 
3844
+ /*
3845
+ * Document-method: Zlib::GzipReader.zcat
3846
+ *
3847
+ * call-seq:
3848
+ * Zlib::GzipReader.zcat(io, options = {}, &block) => nil
3849
+ * Zlib::GzipReader.zcat(io, options = {}) => string
3850
+ *
3851
+ * Decompresses all gzip data in the +io+, handling multiple gzip
3852
+ * streams until the end of the +io+. There should not be any non-gzip
3853
+ * data after the gzip streams.
3854
+ *
3855
+ * If a block is given, it is yielded strings of uncompressed data,
3856
+ * and the method returns +nil+.
3857
+ * If a block is not given, the method returns the concatenation of
3858
+ * all uncompressed data in all gzip streams.
3859
+ */
3860
+ static VALUE
3861
+ rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
3862
+ {
3863
+ VALUE io, unused, obj, buf=0, tmpbuf;
3864
+ long pos;
3865
+
3866
+ rb_check_arity(argc, 1, 2);
3867
+ io = argv[0];
3868
+
3869
+ do {
3870
+ obj = rb_funcallv(klass, rb_intern("new"), argc, argv);
3871
+ if (rb_block_given_p()) {
3872
+ rb_gzreader_each(0, 0, obj);
3873
+ }
3874
+ else {
3875
+ if (!buf) {
3876
+ buf = rb_str_new(0, 0);
3877
+ }
3878
+ tmpbuf = gzfile_read_all(get_gzfile(obj));
3879
+ rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
3880
+ }
3881
+
3882
+ rb_gzreader_read(0, 0, obj);
3883
+ pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0));
3884
+ unused = rb_gzreader_unused(obj);
3885
+ rb_gzfile_finish(obj);
3886
+ if (!NIL_P(unused)) {
3887
+ pos -= NUM2LONG(rb_funcall(unused, rb_intern("length"), 0));
3888
+ rb_funcall(io, rb_intern("pos="), 1, LONG2NUM(pos));
3889
+ }
3890
+ } while (pos < NUM2LONG(rb_funcall(io, rb_intern("size"), 0)));
3891
+
3892
+ if (rb_block_given_p()) {
3893
+ return Qnil;
3894
+ }
3895
+ return buf;
3896
+ }
3897
+
3695
3898
  /*
3696
3899
  * Document-method: Zlib::GzipReader.new
3697
3900
  *
@@ -3726,12 +3929,12 @@ rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
3726
3929
  }
3727
3930
  gz->io = io;
3728
3931
  ZSTREAM_READY(&gz->z);
3729
- gzfile_read_header(gz);
3932
+ gzfile_read_header(gz, Qnil);
3730
3933
  rb_gzfile_ecopts(gz, opt);
3731
3934
 
3732
3935
  if (rb_respond_to(io, id_path)) {
3733
- gz->path = rb_funcall(gz->io, id_path, 0);
3734
- rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3936
+ /* File#path may raise IOError in case when a path is unavailable */
3937
+ rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
3735
3938
  }
3736
3939
 
3737
3940
  return obj;
@@ -3918,20 +4121,6 @@ rb_gzreader_each_byte(VALUE obj)
3918
4121
  return Qnil;
3919
4122
  }
3920
4123
 
3921
- /*
3922
- * Document-method: Zlib::GzipReader#bytes
3923
- *
3924
- * This is a deprecated alias for <code>each_byte</code>.
3925
- */
3926
- static VALUE
3927
- rb_gzreader_bytes(VALUE obj)
3928
- {
3929
- rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
3930
- if (!rb_block_given_p())
3931
- return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
3932
- return rb_gzreader_each_byte(obj);
3933
- }
3934
-
3935
4124
  /*
3936
4125
  * Document-method: Zlib::GzipReader#ungetc
3937
4126
  *
@@ -3976,7 +4165,7 @@ gzreader_skip_linebreaks(struct gzfile *gz)
3976
4165
 
3977
4166
  while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
3978
4167
  if (GZFILE_IS_FINISHED(gz)) return;
3979
- gzfile_read_more(gz);
4168
+ gzfile_read_more(gz, Qnil);
3980
4169
  }
3981
4170
  n = 0;
3982
4171
  p = RSTRING_PTR(gz->z.buf);
@@ -3987,7 +4176,7 @@ gzreader_skip_linebreaks(struct gzfile *gz)
3987
4176
  gzfile_calc_crc(gz, str);
3988
4177
  while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
3989
4178
  if (GZFILE_IS_FINISHED(gz)) return;
3990
- gzfile_read_more(gz);
4179
+ gzfile_read_more(gz, Qnil);
3991
4180
  }
3992
4181
  n = 0;
3993
4182
  p = RSTRING_PTR(gz->z.buf);
@@ -4109,7 +4298,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
4109
4298
  if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
4110
4299
  return gzfile_read(gz, rslen);
4111
4300
  }
4112
- gzfile_read_more(gz);
4301
+ gzfile_read_more(gz, Qnil);
4113
4302
  }
4114
4303
 
4115
4304
  p = RSTRING_PTR(gz->z.buf);
@@ -4118,7 +4307,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
4118
4307
  long filled;
4119
4308
  if (n > ZSTREAM_BUF_FILLED(&gz->z)) {
4120
4309
  if (ZSTREAM_IS_FINISHED(&gz->z)) break;
4121
- gzfile_read_more(gz);
4310
+ gzfile_read_more(gz, Qnil);
4122
4311
  p = RSTRING_PTR(gz->z.buf) + n - rslen;
4123
4312
  }
4124
4313
  if (!rspara) rscheck(rsptr, rslen, rs);
@@ -4158,6 +4347,8 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
4158
4347
  * Document-method: Zlib::GzipReader#gets
4159
4348
  *
4160
4349
  * See Zlib::GzipReader documentation for a description.
4350
+ * However, note that this method can return +nil+ even if
4351
+ * #eof? returns false, unlike the behavior of File#gets.
4161
4352
  */
4162
4353
  static VALUE
4163
4354
  rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
@@ -4204,20 +4395,6 @@ rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
4204
4395
  return obj;
4205
4396
  }
4206
4397
 
4207
- /*
4208
- * Document-method: Zlib::GzipReader#lines
4209
- *
4210
- * This is a deprecated alias for <code>each_line</code>.
4211
- */
4212
- static VALUE
4213
- rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
4214
- {
4215
- rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
4216
- if (!rb_block_given_p())
4217
- return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
4218
- return rb_gzreader_each(argc, argv, obj);
4219
- }
4220
-
4221
4398
  /*
4222
4399
  * Document-method: Zlib::GzipReader#readlines
4223
4400
  *
@@ -4245,6 +4422,20 @@ rb_gzreader_external_encoding(VALUE self)
4245
4422
  return rb_enc_from_encoding(get_gzfile(self)->enc);
4246
4423
  }
4247
4424
 
4425
+ static VALUE
4426
+ zlib_gzip_end_rescue(VALUE arg)
4427
+ {
4428
+ struct gzfile *gz = (struct gzfile *)arg;
4429
+ gz->end(gz);
4430
+ return Qnil;
4431
+ }
4432
+
4433
+ static VALUE
4434
+ zlib_gzip_ensure(VALUE arg)
4435
+ {
4436
+ return rb_rescue(zlib_gzip_end_rescue, arg, NULL, Qnil);
4437
+ }
4438
+
4248
4439
  static void
4249
4440
  zlib_gzip_end(struct gzfile *gz)
4250
4441
  {
@@ -4254,9 +4445,8 @@ zlib_gzip_end(struct gzfile *gz)
4254
4445
  zstream_end(&gz->z);
4255
4446
  }
4256
4447
 
4257
- #define OPTHASH_GIVEN_P(opts) \
4258
- (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
4259
4448
  static ID id_level, id_strategy;
4449
+ static VALUE zlib_gzip_run(VALUE arg);
4260
4450
 
4261
4451
  /*
4262
4452
  * call-seq:
@@ -4285,9 +4475,8 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
4285
4475
  {
4286
4476
  struct gzfile gz0;
4287
4477
  struct gzfile *gz = &gz0;
4288
- long len;
4289
4478
  int err;
4290
- VALUE src, opts, level=Qnil, strategy=Qnil;
4479
+ VALUE src, opts, level=Qnil, strategy=Qnil, args[2];
4291
4480
 
4292
4481
  if (OPTHASH_GIVEN_P(opts)) {
4293
4482
  ID keyword_ids[2];
@@ -4309,9 +4498,23 @@ zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
4309
4498
  err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
4310
4499
  -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
4311
4500
  if (err != Z_OK) {
4501
+ zlib_gzip_end(gz);
4312
4502
  raise_zlib_error(err, gz->z.stream.msg);
4313
4503
  }
4314
4504
  ZSTREAM_READY(&gz->z);
4505
+ args[0] = (VALUE)gz;
4506
+ args[1] = src;
4507
+ return rb_ensure(zlib_gzip_run, (VALUE)args, zlib_gzip_ensure, (VALUE)gz);
4508
+ }
4509
+
4510
+ static VALUE
4511
+ zlib_gzip_run(VALUE arg)
4512
+ {
4513
+ VALUE *args = (VALUE *)arg;
4514
+ struct gzfile *gz = (struct gzfile *)args[0];
4515
+ VALUE src = args[1];
4516
+ long len;
4517
+
4315
4518
  gzfile_make_header(gz);
4316
4519
  len = RSTRING_LEN(src);
4317
4520
  if (len > 0) {
@@ -4327,10 +4530,11 @@ static void
4327
4530
  zlib_gunzip_end(struct gzfile *gz)
4328
4531
  {
4329
4532
  gz->z.flags |= ZSTREAM_FLAG_CLOSING;
4330
- gzfile_check_footer(gz);
4331
4533
  zstream_end(&gz->z);
4332
4534
  }
4333
4535
 
4536
+ static VALUE zlib_gunzip_run(VALUE arg);
4537
+
4334
4538
  /*
4335
4539
  * call-seq:
4336
4540
  * Zlib.gunzip(src) -> String
@@ -4355,7 +4559,6 @@ zlib_gunzip(VALUE klass, VALUE src)
4355
4559
  struct gzfile gz0;
4356
4560
  struct gzfile *gz = &gz0;
4357
4561
  int err;
4358
- VALUE dst;
4359
4562
 
4360
4563
  StringValue(src);
4361
4564
 
@@ -4367,15 +4570,25 @@ zlib_gunzip(VALUE klass, VALUE src)
4367
4570
  gz->io = Qundef;
4368
4571
  gz->z.input = src;
4369
4572
  ZSTREAM_READY(&gz->z);
4370
- gzfile_read_header(gz);
4573
+ return rb_ensure(zlib_gunzip_run, (VALUE)gz, zlib_gzip_ensure, (VALUE)gz);
4574
+ }
4575
+
4576
+ static VALUE
4577
+ zlib_gunzip_run(VALUE arg)
4578
+ {
4579
+ struct gzfile *gz = (struct gzfile *)arg;
4580
+ VALUE dst;
4581
+
4582
+ gzfile_read_header(gz, Qnil);
4371
4583
  dst = zstream_detach_buffer(&gz->z);
4372
4584
  gzfile_calc_crc(gz, dst);
4373
- if (!ZSTREAM_IS_FINISHED(&gz->z)) {
4374
- rb_raise(cGzError, "unexpected end of file");
4375
- }
4376
- if (NIL_P(gz->z.input))
4585
+ if (!ZSTREAM_IS_FINISHED(&gz->z)) {
4586
+ rb_raise(cGzError, "unexpected end of file");
4587
+ }
4588
+ if (NIL_P(gz->z.input)) {
4377
4589
  rb_raise(cNoFooter, "footer is not found");
4378
- gzfile_check_footer(gz);
4590
+ }
4591
+ gzfile_check_footer(gz, Qnil);
4379
4592
  return dst;
4380
4593
  }
4381
4594
 
@@ -4384,6 +4597,11 @@ zlib_gunzip(VALUE klass, VALUE src)
4384
4597
  void
4385
4598
  Init_zlib(void)
4386
4599
  {
4600
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
4601
+ rb_ext_ractor_safe(true);
4602
+ #endif
4603
+
4604
+ #undef rb_intern
4387
4605
  VALUE mZlib, cZStream, cDeflate, cInflate;
4388
4606
  #if GZIP_SUPPORT
4389
4607
  VALUE cGzipFile, cGzipWriter, cGzipReader;
@@ -4477,7 +4695,7 @@ Init_zlib(void)
4477
4695
  rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
4478
4696
  rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
4479
4697
  rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
4480
- rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
4698
+ rb_define_method(cInflate, "inflate", rb_inflate_inflate, -1);
4481
4699
  rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
4482
4700
  rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
4483
4701
  rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
@@ -4618,7 +4836,7 @@ Init_zlib(void)
4618
4836
  rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
4619
4837
  rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
4620
4838
  rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
4621
- rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
4839
+ rb_define_method(cGzipWriter, "write", rb_gzwriter_write, -1);
4622
4840
  rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
4623
4841
  rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
4624
4842
  rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
@@ -4626,6 +4844,7 @@ Init_zlib(void)
4626
4844
  rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
4627
4845
 
4628
4846
  rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
4847
+ rb_define_singleton_method(cGzipReader, "zcat", rb_gzreader_s_zcat, -1);
4629
4848
  rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
4630
4849
  rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
4631
4850
  rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
@@ -4638,14 +4857,12 @@ Init_zlib(void)
4638
4857
  rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
4639
4858
  rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
4640
4859
  rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
4641
- rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
4642
4860
  rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
4643
4861
  rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
4644
4862
  rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
4645
4863
  rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
4646
4864
  rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
4647
4865
  rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
4648
- rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
4649
4866
  rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
4650
4867
  rb_define_method(cGzipReader, "external_encoding", rb_gzreader_external_encoding, 0);
4651
4868
 
@@ -4687,6 +4904,7 @@ Init_zlib(void)
4687
4904
 
4688
4905
  id_level = rb_intern("level");
4689
4906
  id_strategy = rb_intern("strategy");
4907
+ id_buffer = rb_intern("buffer");
4690
4908
  #endif /* GZIP_SUPPORT */
4691
4909
  }
4692
4910
 
@@ -4807,5 +5025,3 @@ Init_zlib(void)
4807
5025
  * Raised when the data length recorded in the gzip file footer is not equivalent
4808
5026
  * to the length of the actual uncompressed data.
4809
5027
  */
4810
-
4811
-