Project

General

Profile

Feature #14319 ยป 0001-zlib-reduce-garbage-on-Zlib-GzipReader-readpartial.patch

normalperson (Eric Wong), 01/05/2018 09:03 PM

View differences:

ext/zlib/zlib.c
static void gzfile_write_raw(struct gzfile*);
static VALUE gzfile_read_raw_partial(VALUE);
static VALUE gzfile_read_raw_rescue(VALUE);
static VALUE gzfile_read_raw(struct gzfile*);
static int gzfile_read_raw_ensure(struct gzfile*, long);
static VALUE gzfile_read_raw(struct gzfile*, VALUE outbuf);
static int gzfile_read_raw_ensure(struct gzfile*, long, VALUE outbuf);
static char *gzfile_read_raw_until_zero(struct gzfile*, long);
static unsigned int gzfile_get16(const unsigned char*);
static unsigned long gzfile_get32(const unsigned char*);
static void gzfile_set32(unsigned long n, unsigned char*);
static void gzfile_make_header(struct gzfile*);
static void gzfile_make_footer(struct gzfile*);
static void gzfile_read_header(struct gzfile*);
static void gzfile_check_footer(struct gzfile*);
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*);
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*);
......
#define GZFILE_READ_SIZE 2048
struct read_raw_arg {
VALUE io;
union {
const VALUE argv[2]; /* for rb_funcallv */
struct {
VALUE len;
VALUE buf;
} in;
} as;
};
static void
gzfile_mark(void *p)
......
static VALUE
gzfile_read_raw_partial(VALUE arg)
{
struct gzfile *gz = (struct gzfile*)arg;
struct read_raw_arg *ra = (struct read_raw_arg *)arg;
VALUE str;
int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
str = rb_funcall(gz->io, id_readpartial, 1, INT2FIX(GZFILE_READ_SIZE));
str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv);
Check_Type(str, T_STRING);
return str;
}
......
static VALUE
gzfile_read_raw_rescue(VALUE arg)
{
struct gzfile *gz = (struct gzfile*)arg;
struct read_raw_arg *ra = (struct read_raw_arg *)arg;
VALUE str = Qnil;
if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
str = rb_funcallv(ra->io, id_read, argc, ra->as.argv);
if (!NIL_P(str)) {
Check_Type(str, T_STRING);
}
......
}
static VALUE
gzfile_read_raw(struct gzfile *gz)
gzfile_read_raw(struct gzfile *gz, VALUE outbuf)
{
return rb_rescue2(gzfile_read_raw_partial, (VALUE)gz,
gzfile_read_raw_rescue, (VALUE)gz,
struct read_raw_arg ra;
ra.io = gz->io;
ra.as.in.len = INT2FIX(GZFILE_READ_SIZE);
ra.as.in.buf = outbuf;
return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
gzfile_read_raw_rescue, (VALUE)&ra,
rb_eEOFError, rb_eNoMethodError, (VALUE)0);
}
static int
gzfile_read_raw_ensure(struct gzfile *gz, long size)
gzfile_read_raw_ensure(struct gzfile *gz, long size, VALUE outbuf)
{
VALUE str;
......
rb_raise(cGzError, "unexpected end of string");
}
while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
str = gzfile_read_raw(gz);
str = gzfile_read_raw(gz, outbuf);
if (NIL_P(str)) return 0;
zstream_append_input2(&gz->z, str);
}
......
p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
RSTRING_LEN(gz->z.input) - offset);
if (p) break;
str = gzfile_read_raw(gz);
str = gzfile_read_raw(gz, Qnil);
if (NIL_P(str)) {
rb_raise(cGzError, "unexpected end of file");
}
......
}
static void
gzfile_read_header(struct gzfile *gz)
gzfile_read_header(struct gzfile *gz, VALUE outbuf)
{
const unsigned char *head;
long len;
char flags, *p;
if (!gzfile_read_raw_ensure(gz, 10)) { /* 10 is the size of gzip header */
/* 10 is the size of gzip header */
if (!gzfile_read_raw_ensure(gz, 10, outbuf)) {
gzfile_raise(gz, cGzError, "not in gzip format");
}
......
zstream_discard_input(&gz->z, 10);
if (flags & GZ_FLAG_EXTRA) {
if (!gzfile_read_raw_ensure(gz, 2)) {
if (!gzfile_read_raw_ensure(gz, 2, outbuf)) {
rb_raise(cGzError, "unexpected end of file");
}
len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
if (!gzfile_read_raw_ensure(gz, 2 + len)) {
if (!gzfile_read_raw_ensure(gz, 2 + len, outbuf)) {
rb_raise(cGzError, "unexpected end of file");
}
zstream_discard_input(&gz->z, 2 + len);
}
if (flags & GZ_FLAG_ORIG_NAME) {
if (!gzfile_read_raw_ensure(gz, 1)) {
if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
rb_raise(cGzError, "unexpected end of file");
}
p = gzfile_read_raw_until_zero(gz, 0);
......
zstream_discard_input(&gz->z, len + 1);
}
if (flags & GZ_FLAG_COMMENT) {
if (!gzfile_read_raw_ensure(gz, 1)) {
if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
rb_raise(cGzError, "unexpected end of file");
}
p = gzfile_read_raw_until_zero(gz, 0);
......
}
static void
gzfile_check_footer(struct gzfile *gz)
gzfile_check_footer(struct gzfile *gz, VALUE outbuf)
{
unsigned long crc, length;
gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
if (!gzfile_read_raw_ensure(gz, 8)) { /* 8 is the size of gzip footer */
/* 8 is the size of gzip footer */
if (!gzfile_read_raw_ensure(gz, 8, outbuf)) {
gzfile_raise(gz, cNoFooter, "footer is not found");
}
......
}
static long
gzfile_read_more(struct gzfile *gz)
gzfile_read_more(struct gzfile *gz, VALUE outbuf)
{
VALUE str;
while (!ZSTREAM_IS_FINISHED(&gz->z)) {
str = gzfile_read_raw(gz);
str = gzfile_read_raw(gz, outbuf);
if (NIL_P(str)) {
if (!ZSTREAM_IS_FINISHED(&gz->z)) {
rb_raise(cGzError, "unexpected end of file");
......
if (len == 0)
return 0;
while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
gzfile_check_footer(gz);
gzfile_check_footer(gz, Qnil);
}
return -1;
}
......
}
}
while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
gzfile_read_more(gz);
gzfile_read_more(gz, outbuf);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
gzfile_check_footer(gz);
gzfile_check_footer(gz, outbuf);
}
if (!NIL_P(outbuf))
rb_str_resize(outbuf, 0);
......
if (!NIL_P(outbuf)) {
rb_str_resize(outbuf, RSTRING_LEN(dst));
memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
RB_GC_GUARD(dst);
rb_str_resize(dst, 0);
rb_gc_force_recycle(dst);
dst = outbuf;
}
OBJ_TAINT(dst); /* for safe */
......
VALUE dst;
while (!ZSTREAM_IS_FINISHED(&gz->z)) {
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
gzfile_check_footer(gz);
gzfile_check_footer(gz, Qnil);
}
return rb_str_new(0, 0);
}
......
len = rb_enc_mbmaxlen(gz->enc);
while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
gzfile_check_footer(gz);
gzfile_check_footer(gz, Qnil);
}
return Qnil;
}
......
if (GZFILE_IS_FINISHED(gz)
&& !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
gzfile_check_footer(gz);
gzfile_check_footer(gz, Qnil);
}
return Qnil;
......
if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
if (!GZFILE_IS_FINISHED(gz)) return Qnil;
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
gzfile_check_footer(gz);
gzfile_check_footer(gz, Qnil);
}
if (NIL_P(gz->z.input)) return Qnil;
......
}
gz->io = io;
ZSTREAM_READY(&gz->z);
gzfile_read_header(gz);
gzfile_read_header(gz, Qnil);
rb_gzfile_ecopts(gz, opt);
if (rb_respond_to(io, id_path)) {
......
while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
if (GZFILE_IS_FINISHED(gz)) return;
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
}
n = 0;
p = RSTRING_PTR(gz->z.buf);
......
gzfile_calc_crc(gz, str);
while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
if (GZFILE_IS_FINISHED(gz)) return;
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
}
n = 0;
p = RSTRING_PTR(gz->z.buf);
......
if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
return gzfile_read(gz, rslen);
}
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
}
p = RSTRING_PTR(gz->z.buf);
......
long filled;
if (n > ZSTREAM_BUF_FILLED(&gz->z)) {
if (ZSTREAM_IS_FINISHED(&gz->z)) break;
gzfile_read_more(gz);
gzfile_read_more(gz, Qnil);
p = RSTRING_PTR(gz->z.buf) + n - rslen;
}
if (!rspara) rscheck(rsptr, rslen, rs);
......
struct gzfile *gz = (struct gzfile *)arg;
VALUE dst;
gzfile_read_header(gz);
gzfile_read_header(gz, Qnil);
dst = zstream_detach_buffer(&gz->z);
gzfile_calc_crc(gz, dst);
if (!ZSTREAM_IS_FINISHED(&gz->z)) {
......
if (NIL_P(gz->z.input)) {
rb_raise(cNoFooter, "footer is not found");
}
gzfile_check_footer(gz);
gzfile_check_footer(gz, Qnil);
return dst;
}
-
    (1-1/1)