summaryrefslogtreecommitdiff
path: root/ext/zlib
diff options
context:
space:
mode:
Diffstat (limited to 'ext/zlib')
-rw-r--r--ext/zlib/depend6
-rw-r--r--ext/zlib/extconf.rb15
-rw-r--r--ext/zlib/extlibs8
-rw-r--r--ext/zlib/win32/zlib-1.2.11-mswin.patch95
-rw-r--r--ext/zlib/zlib.c268
-rw-r--r--ext/zlib/zlib.gemspec2
6 files changed, 185 insertions, 209 deletions
diff --git a/ext/zlib/depend b/ext/zlib/depend
index d63d388c9e..bdce420264 100644
--- a/ext/zlib/depend
+++ b/ext/zlib/depend
@@ -7,7 +7,6 @@ zlib.o: $(hdrdir)/ruby/backward.h
zlib.o: $(hdrdir)/ruby/backward/2/assume.h
zlib.o: $(hdrdir)/ruby/backward/2/attributes.h
zlib.o: $(hdrdir)/ruby/backward/2/bool.h
-zlib.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
zlib.o: $(hdrdir)/ruby/backward/2/inttypes.h
zlib.o: $(hdrdir)/ruby/backward/2/limits.h
zlib.o: $(hdrdir)/ruby/backward/2/long_long.h
@@ -16,6 +15,7 @@ zlib.o: $(hdrdir)/ruby/backward/2/stdarg.h
zlib.o: $(hdrdir)/ruby/defines.h
zlib.o: $(hdrdir)/ruby/encoding.h
zlib.o: $(hdrdir)/ruby/intern.h
+zlib.o: $(hdrdir)/ruby/internal/abi.h
zlib.o: $(hdrdir)/ruby/internal/anyargs.h
zlib.o: $(hdrdir)/ruby/internal/arithmetic.h
zlib.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -53,6 +53,7 @@ zlib.o: $(hdrdir)/ruby/internal/attr/noexcept.h
zlib.o: $(hdrdir)/ruby/internal/attr/noinline.h
zlib.o: $(hdrdir)/ruby/internal/attr/nonnull.h
zlib.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+zlib.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
zlib.o: $(hdrdir)/ruby/internal/attr/pure.h
zlib.o: $(hdrdir)/ruby/internal/attr/restrict.h
zlib.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
@@ -121,7 +122,6 @@ zlib.o: $(hdrdir)/ruby/internal/intern/enumerator.h
zlib.o: $(hdrdir)/ruby/internal/intern/error.h
zlib.o: $(hdrdir)/ruby/internal/intern/eval.h
zlib.o: $(hdrdir)/ruby/internal/intern/file.h
-zlib.o: $(hdrdir)/ruby/internal/intern/gc.h
zlib.o: $(hdrdir)/ruby/internal/intern/hash.h
zlib.o: $(hdrdir)/ruby/internal/intern/io.h
zlib.o: $(hdrdir)/ruby/internal/intern/load.h
@@ -152,12 +152,12 @@ zlib.o: $(hdrdir)/ruby/internal/memory.h
zlib.o: $(hdrdir)/ruby/internal/method.h
zlib.o: $(hdrdir)/ruby/internal/module.h
zlib.o: $(hdrdir)/ruby/internal/newobj.h
-zlib.o: $(hdrdir)/ruby/internal/rgengc.h
zlib.o: $(hdrdir)/ruby/internal/scan_args.h
zlib.o: $(hdrdir)/ruby/internal/special_consts.h
zlib.o: $(hdrdir)/ruby/internal/static_assert.h
zlib.o: $(hdrdir)/ruby/internal/stdalign.h
zlib.o: $(hdrdir)/ruby/internal/stdbool.h
+zlib.o: $(hdrdir)/ruby/internal/stdckdint.h
zlib.o: $(hdrdir)/ruby/internal/symbol.h
zlib.o: $(hdrdir)/ruby/internal/value.h
zlib.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/zlib/extconf.rb b/ext/zlib/extconf.rb
index d674544f22..2b2dbb1a5b 100644
--- a/ext/zlib/extconf.rb
+++ b/ext/zlib/extconf.rb
@@ -11,10 +11,9 @@ require 'rbconfig'
dir_config 'zlib'
libs = $libs
-if %w'z libz zlib1 zlib zdll zlibwapi'.find {|z| have_library(z, 'deflateReset')} and
- have_header('zlib.h') then
- have_zlib = true
-else
+have_zlib = %w'z libz zlib1 zlib zdll zlibwapi'.any? {|z| have_library(z, 'deflateReset(NULL)', 'zlib.h')}
+
+unless have_zlib
$libs = libs
unless File.directory?(zsrc = "#{$srcdir}/zlib")
dirs = Dir.open($srcdir) {|z| z.grep(/\Azlib-\d+[.\d]*\z/) {|x|"#{$srcdir}/#{x}"}}
@@ -121,10 +120,18 @@ if have_zlib
$defs << "-DHAVE_CRC32_COMBINE"
$defs << "-DHAVE_ADLER32_COMBINE"
$defs << "-DHAVE_TYPE_Z_CRC_T"
+ $defs << "-DHAVE_CRC32_Z"
+ $defs << "-DHAVE_ADLER32_Z"
+ $defs << "-DHAVE_ZLIB_SIZE_T_FUNCS"
else
have_func('crc32_combine', 'zlib.h')
have_func('adler32_combine', 'zlib.h')
have_type('z_crc_t', 'zlib.h')
+ if (have_type('z_size_t', 'zlib.h') &&
+ have_func('crc32_z', 'zlib.h') &&
+ have_func('adler32_z', 'zlib.h'))
+ $defs << "-DHAVE_ZLIB_SIZE_T_FUNCS"
+ end
end
create_makefile('zlib') {|conf|
diff --git a/ext/zlib/extlibs b/ext/zlib/extlibs
deleted file mode 100644
index a64b37ba5f..0000000000
--- a/ext/zlib/extlibs
+++ /dev/null
@@ -1,8 +0,0 @@
-ver = 1.2.11
-pkg = zlib-$(ver)
-
-https://zlib.net/$(pkg).tar.gz \
- md5:1c9f62f0778697a09d36121ead88e08e \
- sha512:73fd3fff4adeccd4894084c15ddac89890cd10ef105dd5e1835e1e9bbb6a49ff229713bd197d203edfa17c2727700fce65a2a235f07568212d820dca88b528ae \
- #
- win32/$(pkg)-mswin.patch -p0
diff --git a/ext/zlib/win32/zlib-1.2.11-mswin.patch b/ext/zlib/win32/zlib-1.2.11-mswin.patch
deleted file mode 100644
index 8810b4403c..0000000000
--- a/ext/zlib/win32/zlib-1.2.11-mswin.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-diff -ru zlib-1.2.11/gzread.c zlib-1.2.11/gzread.c
---- zlib-1.2.11/gzread.c 2016-12-31 23:37:10.000000000 +0900
-+++ zlib-1.2.11/gzread.c 2020-11-23 19:35:00.550987184 +0900
-@@ -316,7 +316,7 @@
- /* set n to the maximum amount of len that fits in an unsigned int */
- n = -1;
- if (n > len)
-- n = len;
-+ n = (unsigned)len;
-
- /* first just try copying data from the output buffer */
- if (state->x.have) {
-@@ -397,7 +397,7 @@
- }
-
- /* read len or fewer bytes to buf */
-- len = gz_read(state, buf, len);
-+ len = (unsigned)gz_read(state, buf, len);
-
- /* check for an error */
- if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
-@@ -469,7 +469,7 @@
- }
-
- /* nothing there -- try gz_read() */
-- ret = gz_read(state, buf, 1);
-+ ret = (int)gz_read(state, buf, 1);
- return ret < 1 ? -1 : buf[0];
- }
-
-diff -ru zlib-1.2.11/gzwrite.c zlib-1.2.11/gzwrite.c
---- zlib-1.2.11/gzwrite.c 2017-01-15 09:29:40.000000000 +0900
-+++ zlib-1.2.11/gzwrite.c 2020-11-23 19:35:41.530494030 +0900
-@@ -209,7 +209,7 @@
- state->in);
- copy = state->size - have;
- if (copy > len)
-- copy = len;
-+ copy = (unsigned)len;
- memcpy(state->in + have, buf, copy);
- state->strm.avail_in += copy;
- state->x.pos += copy;
-@@ -229,7 +229,7 @@
- do {
- unsigned n = (unsigned)-1;
- if (n > len)
-- n = len;
-+ n = (unsigned)len;
- state->strm.avail_in = n;
- state->x.pos += n;
- if (gz_comp(state, Z_NO_FLUSH) == -1)
-@@ -368,7 +368,7 @@
-
- /* write string */
- len = strlen(str);
-- ret = gz_write(state, str, len);
-+ ret = (int)gz_write(state, str, len);
- return ret == 0 && len != 0 ? -1 : ret;
- }
-
-diff -ru zlib-1.2.11/win32/Makefile.msc zlib-1.2.11/win32/Makefile.msc
---- zlib-1.2.11/win32/Makefile.msc 2017-01-15 09:07:08.000000000 +0900
-+++ zlib-1.2.11/win32/Makefile.msc 2020-11-23 22:37:19.746500208 +0900
-@@ -37,6 +37,22 @@
- gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj
- OBJA =
-
-+!ifdef USE_ASM
-+LOC = -DASMV -DASMINF
-+!if "$(ARCH)" == "i386"
-+OBJA = inffas32.obj match686.obj
-+!else if "$(ARCH)" == "x64"
-+AS = ml64
-+LOC = $(LOC) -I.
-+OBJA = inffasx64.obj gvmat64.obj inffas8664.obj
-+!endif
-+!endif
-+
-+!if "$(ARCH)" == "x64"
-+ZBASE = 0x5A4C000000
-+!else
-+ZBASE = 0x5A4C0000
-+!endif
-
- # targets
- all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
-@@ -49,7 +65,7 @@
-
- $(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res
- $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \
-- -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res
-+ -out:$@ -base:$(ZBASE) $(OBJS) $(OBJA) zlib1.res
- if exist $@.manifest \
- mt -nologo -manifest $@.manifest -outputresource:$@;2
-
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 9937f82740..aad9f8d28a 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -25,7 +25,7 @@
# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
#endif
-#define RUBY_ZLIB_VERSION "2.1.1"
+#define RUBY_ZLIB_VERSION "3.1.0"
#ifndef RB_PASS_CALLED_KEYWORDS
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
@@ -44,6 +44,14 @@
#endif
#endif
+#if defined(HAVE_ZLIB_SIZE_T_FUNCS)
+typedef uLong (*checksum_func)(uLong, const Bytef*, z_size_t);
+# define crc32 crc32_z
+# define adler32 adler32_z
+#else
+typedef uLong (*checksum_func)(uLong, const Bytef*, uInt);
+#endif
+
#if SIZEOF_LONG > SIZEOF_INT
static inline uInt
max_uint(long n)
@@ -65,7 +73,7 @@ static ID id_dictionaries, id_read, id_buffer;
static NORETURN(void raise_zlib_error(int, const char*));
static VALUE rb_zlib_version(VALUE);
-static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
+static VALUE do_checksum(int, VALUE*, checksum_func);
static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
static VALUE rb_zlib_crc_table(VALUE);
@@ -82,7 +90,7 @@ static void zstream_expand_buffer_into(struct zstream*, unsigned long);
static int zstream_expand_buffer_non_stream(struct zstream *z);
static void zstream_append_buffer(struct zstream*, const Bytef*, long);
static VALUE zstream_detach_buffer(struct zstream*);
-static VALUE zstream_shift_buffer(struct zstream*, long);
+static VALUE zstream_shift_buffer(struct zstream*, long, VALUE);
static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
static void zstream_buffer_ungetbyte(struct zstream*, int);
static void zstream_append_input(struct zstream*, const Bytef*, long);
@@ -162,8 +170,8 @@ static void gzfile_check_footer(struct gzfile*, VALUE outbuf);
static void gzfile_write(struct gzfile*, Bytef*, long);
static long gzfile_read_more(struct gzfile*, VALUE outbuf);
static void gzfile_calc_crc(struct gzfile*, VALUE);
-static VALUE gzfile_read(struct gzfile*, long);
-static VALUE gzfile_read_all(struct gzfile*);
+static VALUE gzfile_read(struct gzfile*, long, VALUE);
+static VALUE gzfile_read_all(struct gzfile*, VALUE);
static void gzfile_ungets(struct gzfile*, const Bytef*, long);
static void gzfile_ungetbyte(struct gzfile*, int);
static VALUE gzfile_writer_end_run(VALUE);
@@ -288,6 +296,7 @@ static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
* - Zlib::MemError
* - Zlib::BufError
* - Zlib::VersionError
+ * - Zlib::InProgressError
*
* (if you have GZIP_SUPPORT)
* - Zlib::GzipReader
@@ -304,7 +313,7 @@ void Init_zlib(void);
/*--------- Exceptions --------*/
static VALUE cZError, cStreamEnd, cNeedDict;
-static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
+static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError, cInProgressError;
static void
raise_zlib_error(int err, const char *msg)
@@ -373,26 +382,32 @@ rb_zlib_version(VALUE klass)
return rb_str_new2(zlibVersion());
}
-#if SIZEOF_LONG > SIZEOF_INT
+#if SIZEOF_LONG * CHAR_BIT > 32
+# define mask32(x) ((x) & 0xffffffff)
+#else
+# define mask32(x) (x)
+#endif
+
+#if SIZEOF_LONG > SIZEOF_INT && !defined(HAVE_ZLIB_SIZE_T_FUNCS)
static uLong
checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
{
if (len > UINT_MAX) {
do {
- sum = func(sum, ptr, UINT_MAX);
+ sum = func(mask32(sum), ptr, UINT_MAX);
ptr += UINT_MAX;
len -= UINT_MAX;
} while (len >= UINT_MAX);
}
- if (len > 0) sum = func(sum, ptr, (uInt)len);
+ if (len > 0) sum = func(mask32(sum), ptr, (uInt)len);
return sum;
}
#else
-#define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
+#define checksum_long(func, sum, ptr, len) (func)(mask32(sum), (ptr), (len))
#endif
static VALUE
-do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
+do_checksum(int argc, VALUE *argv, checksum_func func)
{
VALUE str, vsum;
unsigned long sum;
@@ -410,7 +425,7 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
}
if (NIL_P(str)) {
- sum = func(sum, Z_NULL, 0);
+ sum = func(mask32(sum), Z_NULL, 0);
}
else if (rb_obj_is_kind_of(str, rb_cIO)) {
VALUE buf;
@@ -460,7 +475,7 @@ rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
*
* call-seq: Zlib.adler32_combine(adler1, adler2, len2)
*
- * Combine two Adler-32 check values in to one. +alder1+ is the first Adler-32
+ * Combine two Adler-32 check values in to one. +adler1+ is the first Adler-32
* value, +adler2+ is the second Adler-32 value. +len2+ is the length of the
* string used to generate +adler2+.
*
@@ -557,14 +572,15 @@ struct zstream {
} *func;
};
-#define ZSTREAM_FLAG_READY 0x1
-#define ZSTREAM_FLAG_IN_STREAM 0x2
-#define ZSTREAM_FLAG_FINISHED 0x4
-#define ZSTREAM_FLAG_CLOSING 0x8
-#define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for
+#define ZSTREAM_FLAG_READY (1 << 0)
+#define ZSTREAM_FLAG_IN_STREAM (1 << 1)
+#define ZSTREAM_FLAG_FINISHED (1 << 2)
+#define ZSTREAM_FLAG_CLOSING (1 << 3)
+#define ZSTREAM_FLAG_GZFILE (1 << 4) /* disallows yield from expand_buffer for
gzip*/
-#define ZSTREAM_REUSE_BUFFER 0x20
-#define ZSTREAM_FLAG_UNUSED 0x40
+#define ZSTREAM_REUSE_BUFFER (1 << 5)
+#define ZSTREAM_IN_PROGRESS (1 << 6)
+#define ZSTREAM_FLAG_UNUSED (1 << 7)
#define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
#define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
@@ -593,7 +609,9 @@ static const struct zstream_funcs inflate_funcs = {
};
struct zstream_run_args {
- struct zstream * z;
+ struct zstream *const z;
+ Bytef *src;
+ long len;
int flush; /* stream flush value for inflate() or deflate() */
int interrupt; /* stop processing the stream and return to ruby */
int jump_state; /* for buffer expansion block break or exception */
@@ -802,19 +820,31 @@ zstream_detach_buffer(struct zstream *z)
}
static VALUE
-zstream_shift_buffer(struct zstream *z, long len)
+zstream_shift_buffer(struct zstream *z, long len, VALUE dst)
{
- VALUE dst;
char *bufptr;
long buflen = ZSTREAM_BUF_FILLED(z);
if (buflen <= len) {
- return zstream_detach_buffer(z);
+ if (NIL_P(dst) || (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
+ rb_block_given_p())) {
+ return zstream_detach_buffer(z);
+ } else {
+ bufptr = RSTRING_PTR(z->buf);
+ rb_str_resize(dst, buflen);
+ memcpy(RSTRING_PTR(dst), bufptr, buflen);
+ }
+ buflen = 0;
+ } else {
+ bufptr = RSTRING_PTR(z->buf);
+ if (NIL_P(dst)) {
+ dst = rb_str_new(bufptr, len);
+ } else {
+ rb_str_resize(dst, len);
+ memcpy(RSTRING_PTR(dst), bufptr, len);
+ }
+ buflen -= len;
}
-
- bufptr = RSTRING_PTR(z->buf);
- dst = rb_str_new(bufptr, len);
- buflen -= len;
memmove(bufptr, bufptr + len, buflen);
rb_str_set_len(z->buf, buflen);
z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
@@ -894,7 +924,6 @@ zstream_discard_input(struct zstream *z, long len)
}
rb_str_resize(z->input, newlen);
if (newlen == 0) {
- rb_gc_force_recycle(z->input);
z->input = Qnil;
}
else {
@@ -906,7 +935,7 @@ zstream_discard_input(struct zstream *z, long len)
z->input = Qnil;
}
else {
- z->input = rb_str_substr(z->input, len,
+ z->input = rb_str_subseq(z->input, len,
RSTRING_LEN(z->input) - len);
}
}
@@ -1059,19 +1088,18 @@ zstream_unblock_func(void *ptr)
args->interrupt = 1;
}
-static void
-zstream_run0(struct zstream *z, Bytef *src, long len, int flush)
+static VALUE
+zstream_run_try(VALUE value_arg)
{
- struct zstream_run_args args;
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+ struct zstream *z = args->z;
+ Bytef *src = args->src;
+ long len = args->len;
+ int flush = args->flush;
+
int err;
VALUE old_input = Qnil;
- args.z = z;
- args.flush = flush;
- args.interrupt = 0;
- args.jump_state = 0;
- args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
-
if (NIL_P(z->input) && len == 0) {
z->stream.next_in = (Bytef*)"";
z->stream.avail_in = 0;
@@ -1093,17 +1121,17 @@ zstream_run0(struct zstream *z, Bytef *src, long len, int flush)
loop:
#ifndef RB_NOGVL_UBF_ASYNC_SAFE
- err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
- zstream_unblock_func, (void *)&args);
+ err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)args,
+ zstream_unblock_func, (void *)args);
#else
- err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
- zstream_unblock_func, (void *)&args,
+ err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args,
+ zstream_unblock_func, (void *)args,
RB_NOGVL_UBF_ASYNC_SAFE);
#endif
/* retry if no exception is thrown */
- if (err == Z_OK && args.interrupt) {
- args.interrupt = 0;
+ if (err == Z_OK && args->interrupt) {
+ args->interrupt = 0;
goto loop;
}
@@ -1137,37 +1165,54 @@ loop:
}
if (!NIL_P(old_input)) {
rb_str_resize(old_input, 0);
- rb_gc_force_recycle(old_input);
}
- if (args.jump_state)
- rb_jump_tag(args.jump_state);
+ if (args->jump_state)
+ rb_jump_tag(args->jump_state);
+
+ return Qnil;
}
-struct zstream_run_synchronized_args {
- struct zstream *z;
- Bytef *src;
- long len;
- int flush;
-};
+static VALUE
+zstream_run_ensure(VALUE value_arg)
+{
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+
+ /* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */
+ args->z->flags &= ~ZSTREAM_IN_PROGRESS;
+
+ return Qnil;
+}
static VALUE
zstream_run_synchronized(VALUE value_arg)
{
- struct zstream_run_synchronized_args *run_args = (struct zstream_run_synchronized_args *)value_arg;
- zstream_run0(run_args->z, run_args->src, run_args->len, run_args->flush);
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+
+ /* Cannot start zstream while it is in progress. */
+ if (args->z->flags & ZSTREAM_IN_PROGRESS) {
+ rb_raise(cInProgressError, "zlib stream is in progress");
+ }
+ args->z->flags |= ZSTREAM_IN_PROGRESS;
+
+ rb_ensure(zstream_run_try, value_arg, zstream_run_ensure, value_arg);
+
return Qnil;
}
static void
zstream_run(struct zstream *z, Bytef *src, long len, int flush)
{
- struct zstream_run_synchronized_args run_args;
- run_args.z = z;
- run_args.src = src;
- run_args.len = len;
- run_args.flush = flush;
- rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&run_args);
+ struct zstream_run_args args = {
+ .z = z,
+ .src = src,
+ .len = len,
+ .flush = flush,
+ .interrupt = 0,
+ .jump_state = 0,
+ .stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(),
+ };
+ rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args);
}
static VALUE
@@ -2841,18 +2886,18 @@ gzfile_newstr(struct gzfile *gz, VALUE str)
}
static long
-gzfile_fill(struct gzfile *gz, long len)
+gzfile_fill(struct gzfile *gz, long len, VALUE outbuf)
{
if (len < 0)
rb_raise(rb_eArgError, "negative length %ld given", len);
if (len == 0)
return 0;
while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
- gzfile_read_more(gz, Qnil);
+ gzfile_read_more(gz, outbuf);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
- gzfile_check_footer(gz, Qnil);
+ gzfile_check_footer(gz, outbuf);
}
return -1;
}
@@ -2860,14 +2905,27 @@ gzfile_fill(struct gzfile *gz, long len)
}
static VALUE
-gzfile_read(struct gzfile *gz, long len)
+gzfile_read(struct gzfile *gz, long len, VALUE outbuf)
{
VALUE dst;
- len = gzfile_fill(gz, len);
- if (len == 0) return rb_str_new(0, 0);
- if (len < 0) return Qnil;
- dst = zstream_shift_buffer(&gz->z, len);
+ len = gzfile_fill(gz, len, outbuf);
+
+ if (len < 0) {
+ if (!NIL_P(outbuf))
+ rb_str_resize(outbuf, 0);
+ return Qnil;
+ }
+ if (len == 0) {
+ if (NIL_P(outbuf))
+ return rb_str_new(0, 0);
+ else {
+ rb_str_resize(outbuf, 0);
+ return outbuf;
+ }
+ }
+
+ dst = zstream_shift_buffer(&gz->z, len, outbuf);
if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
return dst;
}
@@ -2900,31 +2958,26 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
rb_raise(rb_eEOFError, "end of file reached");
}
- dst = zstream_shift_buffer(&gz->z, len);
+ dst = zstream_shift_buffer(&gz->z, len, outbuf);
gzfile_calc_crc(gz, dst);
- if (!NIL_P(outbuf)) {
- rb_str_resize(outbuf, RSTRING_LEN(dst));
- memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
- rb_str_resize(dst, 0);
- rb_gc_force_recycle(dst);
- dst = outbuf;
- }
return dst;
}
static VALUE
-gzfile_read_all(struct gzfile *gz)
+gzfile_read_all(struct gzfile *gz, VALUE dst)
{
- VALUE dst;
-
while (!ZSTREAM_IS_FINISHED(&gz->z)) {
- gzfile_read_more(gz, Qnil);
+ gzfile_read_more(gz, dst);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
- gzfile_check_footer(gz, Qnil);
+ gzfile_check_footer(gz, dst);
}
+ if (!NIL_P(dst)) {
+ rb_str_resize(dst, 0);
+ return dst;
+ }
return rb_str_new(0, 0);
}
@@ -2962,7 +3015,7 @@ gzfile_getc(struct gzfile *gz)
de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
(void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
rb_econv_check_error(gz->ec);
- dst = zstream_shift_buffer(&gz->z, sp - ss);
+ dst = zstream_shift_buffer(&gz->z, sp - ss, Qnil);
gzfile_calc_crc(gz, dst);
rb_str_resize(cbuf, dp - ds);
return cbuf;
@@ -2970,7 +3023,7 @@ gzfile_getc(struct gzfile *gz)
else {
buf = gz->z.buf;
len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
- dst = gzfile_read(gz, len);
+ dst = gzfile_read(gz, len, Qnil);
if (NIL_P(dst)) return dst;
return gzfile_newstr(gz, dst);
}
@@ -3469,6 +3522,9 @@ static VALUE
rb_gzfile_eof_p(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
+ gzfile_read_more(gz, Qnil);
+ }
return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
}
@@ -3875,7 +3931,7 @@ rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
if (!buf) {
buf = rb_str_new(0, 0);
}
- tmpbuf = gzfile_read_all(get_gzfile(obj));
+ tmpbuf = gzfile_read_all(get_gzfile(obj), Qnil);
rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
}
@@ -3977,19 +4033,19 @@ static VALUE
rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
- VALUE vlen;
+ VALUE vlen, outbuf;
long len;
- rb_scan_args(argc, argv, "01", &vlen);
+ rb_scan_args(argc, argv, "02", &vlen, &outbuf);
if (NIL_P(vlen)) {
- return gzfile_read_all(gz);
+ return gzfile_read_all(gz, outbuf);
}
len = NUM2INT(vlen);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
- return gzfile_read(gz, len);
+ return gzfile_read(gz, len, outbuf);
}
/*
@@ -4062,7 +4118,7 @@ rb_gzreader_getbyte(VALUE obj)
struct gzfile *gz = get_gzfile(obj);
VALUE dst;
- dst = gzfile_read(gz, 1);
+ dst = gzfile_read(gz, 1, Qnil);
if (!NIL_P(dst)) {
dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
}
@@ -4183,7 +4239,7 @@ gzreader_skip_linebreaks(struct gzfile *gz)
}
}
- str = zstream_shift_buffer(&gz->z, n - 1);
+ str = zstream_shift_buffer(&gz->z, n - 1, Qnil);
gzfile_calc_crc(gz, str);
}
@@ -4204,7 +4260,7 @@ gzreader_charboundary(struct gzfile *gz, long n)
if (l < n) {
int n_bytes = rb_enc_precise_mbclen(p, e, gz->enc);
if (MBCLEN_NEEDMORE_P(n_bytes)) {
- if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes))) > 0) {
+ if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes), Qnil)) > 0) {
return l;
}
}
@@ -4256,10 +4312,10 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
if (NIL_P(rs)) {
if (limit < 0) {
- dst = gzfile_read_all(gz);
+ dst = gzfile_read_all(gz, Qnil);
if (RSTRING_LEN(dst) == 0) return Qnil;
}
- else if ((n = gzfile_fill(gz, limit)) <= 0) {
+ else if ((n = gzfile_fill(gz, limit, Qnil)) <= 0) {
return Qnil;
}
else {
@@ -4269,7 +4325,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
else {
n = limit;
}
- dst = zstream_shift_buffer(&gz->z, n);
+ dst = zstream_shift_buffer(&gz->z, n, Qnil);
if (NIL_P(dst)) return dst;
gzfile_calc_crc(gz, dst);
dst = gzfile_newstr(gz, dst);
@@ -4296,7 +4352,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) {
if (ZSTREAM_IS_FINISHED(&gz->z)) {
if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
- return gzfile_read(gz, rslen);
+ return gzfile_read(gz, rslen, Qnil);
}
gzfile_read_more(gz, Qnil);
}
@@ -4333,7 +4389,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
}
gz->lineno++;
- dst = gzfile_read(gz, n);
+ dst = gzfile_read(gz, n, Qnil);
if (NIL_P(dst)) return dst;
if (rspara) {
gzreader_skip_linebreaks(gz);
@@ -4619,6 +4675,7 @@ Init_zlib(void)
cMemError = rb_define_class_under(mZlib, "MemError", cZError);
cBufError = rb_define_class_under(mZlib, "BufError", cZError);
cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
+ cInProgressError = rb_define_class_under(mZlib, "InProgressError", cZError);
rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
@@ -4926,6 +4983,7 @@ Init_zlib(void)
* - Zlib::MemError
* - Zlib::BufError
* - Zlib::VersionError
+ * - Zlib::InProgressError
*
*/
@@ -5001,6 +5059,20 @@ Init_zlib(void)
*/
/*
+ * Document-class: Zlib::InProgressError
+ *
+ * Subclass of Zlib::Error. This error is raised when the zlib
+ * stream is currently in progress.
+ *
+ * For example:
+ *
+ * inflater = Zlib::Inflate.new
+ * inflater.inflate(compressed) do
+ * inflater.inflate(compressed) # Raises Zlib::InProgressError
+ * end
+ */
+
+/*
* Document-class: Zlib::GzipFile::Error
*
* Base class of errors that occur when processing GZIP files.
diff --git a/ext/zlib/zlib.gemspec b/ext/zlib/zlib.gemspec
index 4a5f8f2ee8..bb67ea156c 100644
--- a/ext/zlib/zlib.gemspec
+++ b/ext/zlib/zlib.gemspec
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
spec.executables = []
spec.require_paths = ["lib"]
spec.extensions = "ext/zlib/extconf.rb"
- spec.required_ruby_version = ">= 2.3.0"
+ spec.required_ruby_version = ">= 2.5.0"
end