ext/zlib/zlib.c in zlib-3.1.1 vs ext/zlib/zlib.c in zlib-3.2.0
- old
+ new
@@ -23,11 +23,11 @@
#else
# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
#endif
-#define RUBY_ZLIB_VERSION "3.1.1"
+#define RUBY_ZLIB_VERSION "3.2.0"
#ifndef RB_PASS_CALLED_KEYWORDS
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
#endif
@@ -88,11 +88,11 @@
static void zstream_expand_buffer(struct zstream*);
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);
static void zstream_discard_input(struct zstream*, long);
static void zstream_reset_input(struct zstream*);
@@ -168,12 +168,12 @@
static void gzfile_read_header(struct gzfile*, VALUE outbuf);
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);
static void gzfile_writer_end(struct gzfile*);
static VALUE gzfile_reader_end_run(VALUE);
@@ -818,23 +818,35 @@
return dst;
}
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);
buflen = (long)rb_str_capacity(z->buf) - ZSTREAM_BUF_FILLED(z);
if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
@@ -1086,10 +1098,16 @@
int flush = args->flush;
int err;
VALUE old_input = Qnil;
+ /* Cannot start zstream while it is in progress. */
+ if (z->flags & ZSTREAM_IN_PROGRESS) {
+ rb_raise(cInProgressError, "zlib stream is in progress");
+ }
+ z->flags |= ZSTREAM_IN_PROGRESS;
+
if (NIL_P(z->input) && len == 0) {
z->stream.next_in = (Bytef*)"";
z->stream.avail_in = 0;
}
else {
@@ -1153,43 +1171,26 @@
}
if (!NIL_P(old_input)) {
rb_str_resize(old_input, 0);
}
- if (args->jump_state)
- rb_jump_tag(args->jump_state);
-
return Qnil;
}
static VALUE
zstream_run_ensure(VALUE value_arg)
{
struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+ struct zstream *z = args->z;
/* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */
- args->z->flags &= ~ZSTREAM_IN_PROGRESS;
+ z->flags &= ~ZSTREAM_IN_PROGRESS;
+ rb_mutex_unlock(z->mutex);
return Qnil;
}
-static VALUE
-zstream_run_synchronized(VALUE value_arg)
-{
- 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_args args = {
.z = z,
@@ -1198,11 +1199,14 @@
.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);
+ rb_mutex_lock(z->mutex);
+ rb_ensure(zstream_run_try, (VALUE)&args, zstream_run_ensure, (VALUE)&args);
+ if (args.jump_state)
+ rb_jump_tag(args.jump_state);
}
static VALUE
zstream_sync(struct zstream *z, Bytef *src, long len)
{
@@ -1507,11 +1511,11 @@
{
return rb_uint2inum(get_zstream(obj)->stream.total_out);
}
/*
- * Guesses the type of the data which have been inputed into the stream. The
+ * Guesses the type of the data which have been inputted into the stream. The
* returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
* <tt>UNKNOWN</tt>.
*/
static VALUE
rb_zstream_data_type(VALUE obj)
@@ -2872,37 +2876,50 @@
return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
gz->ecflags, gz->ecopts);
}
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;
}
return len < ZSTREAM_BUF_FILLED(&gz->z) ? len : ZSTREAM_BUF_FILLED(&gz->z);
}
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;
}
static VALUE
@@ -2931,33 +2948,30 @@
if (!NIL_P(outbuf))
rb_str_resize(outbuf, 0);
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));
- 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);
}
dst = zstream_detach_buffer(&gz->z);
if (NIL_P(dst)) return dst;
@@ -2991,19 +3005,19 @@
se = sp + ZSTREAM_BUF_FILLED(&gz->z);
ds = dp = (unsigned char *)RSTRING_PTR(cbuf);
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;
}
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);
}
}
@@ -3907,11 +3921,11 @@
}
else {
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));
}
rb_gzreader_read(0, 0, obj);
pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0));
@@ -4009,32 +4023,32 @@
*/
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);
}
/*
* Document-method: Zlib::GzipReader#readpartial
*
* call-seq:
* gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
*
- * Reads at most <i>maxlen</i> bytes from the gziped stream but
+ * Reads at most <i>maxlen</i> bytes from the gzipped stream but
* it blocks only if <em>gzipreader</em> has no data immediately available.
* If the optional <i>outbuf</i> argument is present,
* it must reference a String, which will receive the data.
* It raises <code>EOFError</code> on end of file.
*/
@@ -4094,11 +4108,11 @@
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);
}
return dst;
}
@@ -4205,21 +4219,22 @@
p = RSTRING_PTR(gz->z.buf);
while (n++, *(p++) == '\n') {
if (n >= ZSTREAM_BUF_FILLED(&gz->z)) {
str = zstream_detach_buffer(&gz->z);
+ ASSUME(!NIL_P(str));
gzfile_calc_crc(gz, str);
while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
if (GZFILE_IS_FINISHED(gz)) return;
gzfile_read_more(gz, Qnil);
}
n = 0;
p = RSTRING_PTR(gz->z.buf);
}
}
- str = zstream_shift_buffer(&gz->z, n - 1);
+ str = zstream_shift_buffer(&gz->z, n - 1, Qnil);
gzfile_calc_crc(gz, str);
}
static void
rscheck(const char *rsptr, long rslen, VALUE rs)
@@ -4236,11 +4251,11 @@
char *p = rb_enc_left_char_head(s, s + n - 1, e, gz->enc);
long l = p - s;
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;
}
}
else if (MBCLEN_CHARFOUND_P(n_bytes)) {
return l + MBCLEN_CHARFOUND_LEN(n_bytes);
@@ -4288,24 +4303,24 @@
}
}
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 {
if (maxlen > 1 && n >= limit && !GZFILE_IS_FINISHED(gz)) {
n = gzreader_charboundary(gz, n);
}
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);
}
gz->lineno++;
@@ -4328,11 +4343,11 @@
}
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);
}
p = RSTRING_PTR(gz->z.buf);
@@ -4365,11 +4380,11 @@
if (maxlen > 1 && n == limit && (ZSTREAM_BUF_FILLED(&gz->z) > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
n = gzreader_charboundary(gz, n);
}
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);
}
RB_GC_GUARD(rs);
@@ -4613,9 +4628,10 @@
struct gzfile *gz = (struct gzfile *)arg;
VALUE dst;
gzfile_read_header(gz, Qnil);
dst = zstream_detach_buffer(&gz->z);
+ ASSUME(!NIL_P(dst));
gzfile_calc_crc(gz, dst);
if (!ZSTREAM_IS_FINISHED(&gz->z)) {
rb_raise(cGzError, "unexpected end of file");
}
if (NIL_P(gz->z.input)) {