зеркало из https://github.com/github/ruby.git
* ext/zlib/zlib.c (gzreader_gets): support optional length
parameter. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30341 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
aeb8d7f5e5
Коммит
91c6ba2333
|
@ -1,4 +1,7 @@
|
||||||
Sat Dec 25 10:59:12 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sat Dec 25 11:02:52 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* ext/zlib/zlib.c (gzreader_gets): support optional length
|
||||||
|
parameter.
|
||||||
|
|
||||||
* ext/zlib/zlib.c (gzfile_read, gzfile_readpartial): length should
|
* ext/zlib/zlib.c (gzfile_read, gzfile_readpartial): length should
|
||||||
be long.
|
be long.
|
||||||
|
|
102
ext/zlib/zlib.c
102
ext/zlib/zlib.c
|
@ -2204,15 +2204,13 @@ gzfile_newstr(struct gzfile *gz, VALUE str)
|
||||||
gz->ecflags, gz->ecopts);
|
gz->ecflags, gz->ecopts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static long
|
||||||
gzfile_read(struct gzfile *gz, long len)
|
gzfile_fill(struct gzfile *gz, long len)
|
||||||
{
|
{
|
||||||
VALUE dst;
|
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
rb_raise(rb_eArgError, "negative length %ld given", len);
|
rb_raise(rb_eArgError, "negative length %ld given", len);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return rb_str_new(0, 0);
|
return 0;
|
||||||
while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
|
while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
|
||||||
gzfile_read_more(gz);
|
gzfile_read_more(gz);
|
||||||
}
|
}
|
||||||
|
@ -2220,9 +2218,19 @@ gzfile_read(struct gzfile *gz, long len)
|
||||||
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
|
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
|
||||||
gzfile_check_footer(gz);
|
gzfile_check_footer(gz);
|
||||||
}
|
}
|
||||||
return Qnil;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return len < gz->z.buf_filled ? len : gz->z.buf_filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
gzfile_read(struct gzfile *gz, long len)
|
||||||
|
{
|
||||||
|
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);
|
dst = zstream_shift_buffer(&gz->z, len);
|
||||||
gzfile_calc_crc(gz, dst);
|
gzfile_calc_crc(gz, dst);
|
||||||
return dst;
|
return dst;
|
||||||
|
@ -3351,6 +3359,27 @@ rscheck(const char *rsptr, long rslen, VALUE rs)
|
||||||
rb_raise(rb_eRuntimeError, "rs modified");
|
rb_raise(rb_eRuntimeError, "rs modified");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
gzreader_charboundary(struct gzfile *gz, long n)
|
||||||
|
{
|
||||||
|
char *s = RSTRING_PTR(gz->z.buf);
|
||||||
|
char *e = s + gz->z.buf_filled;
|
||||||
|
char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
|
||||||
|
long l = p - s;
|
||||||
|
if (l < n) {
|
||||||
|
n = rb_enc_precise_mbclen(p, e, gz->enc);
|
||||||
|
if (MBCLEN_NEEDMORE_P(n)) {
|
||||||
|
if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (MBCLEN_CHARFOUND_P(n)) {
|
||||||
|
return l + MBCLEN_CHARFOUND_LEN(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
|
@ -3359,24 +3388,57 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
||||||
VALUE dst;
|
VALUE dst;
|
||||||
const char *rsptr;
|
const char *rsptr;
|
||||||
char *p, *res;
|
char *p, *res;
|
||||||
long rslen, n;
|
long rslen, n, limit = -1;
|
||||||
int rspara;
|
int rspara;
|
||||||
|
rb_encoding *enc = gz->enc;
|
||||||
|
int maxlen = rb_enc_mbmaxlen(enc);
|
||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
rs = rb_rs;
|
rs = rb_rs;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_scan_args(argc, argv, "1", &rs);
|
VALUE lim, tmp;
|
||||||
if (!NIL_P(rs)) {
|
|
||||||
Check_Type(rs, T_STRING);
|
rb_scan_args(argc, argv, "11", &rs, &lim);
|
||||||
|
if (!NIL_P(lim)) {
|
||||||
|
if (!NIL_P(rs)) StringValue(rs);
|
||||||
|
}
|
||||||
|
else if (!NIL_P(rs)) {
|
||||||
|
tmp = rb_check_string_type(rs);
|
||||||
|
if (NIL_P(tmp)) {
|
||||||
|
lim = rs;
|
||||||
|
rs = rb_rs;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rs = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!NIL_P(lim)) {
|
||||||
|
limit = NUM2LONG(lim);
|
||||||
|
if (limit == 0) return rb_str_new(0,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NIL_P(rs)) {
|
if (NIL_P(rs)) {
|
||||||
dst = gzfile_read_all(gz);
|
if (limit < 0) {
|
||||||
if (RSTRING_LEN(dst) != 0) gz->lineno++;
|
dst = gzfile_read_all(gz);
|
||||||
else
|
if (RSTRING_LEN(dst) == 0) return Qnil;
|
||||||
|
}
|
||||||
|
else if ((n = gzfile_fill(gz, limit)) <= 0) {
|
||||||
return Qnil;
|
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);
|
||||||
|
gzfile_calc_crc(gz, dst);
|
||||||
|
dst = gzfile_newstr(gz, dst);
|
||||||
|
}
|
||||||
|
gz->lineno++;
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3405,15 +3467,22 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
||||||
p = RSTRING_PTR(gz->z.buf);
|
p = RSTRING_PTR(gz->z.buf);
|
||||||
n = rslen;
|
n = rslen;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
long filled;
|
||||||
if (n > gz->z.buf_filled) {
|
if (n > gz->z.buf_filled) {
|
||||||
if (ZSTREAM_IS_FINISHED(&gz->z)) break;
|
if (ZSTREAM_IS_FINISHED(&gz->z)) break;
|
||||||
gzfile_read_more(gz);
|
gzfile_read_more(gz);
|
||||||
p = RSTRING_PTR(gz->z.buf) + n - rslen;
|
p = RSTRING_PTR(gz->z.buf) + n - rslen;
|
||||||
}
|
}
|
||||||
if (!rspara) rscheck(rsptr, rslen, rs);
|
if (!rspara) rscheck(rsptr, rslen, rs);
|
||||||
res = memchr(p, rsptr[0], (gz->z.buf_filled - n + 1));
|
filled = gz->z.buf_filled;
|
||||||
|
if (limit > 0 && filled >= limit) {
|
||||||
|
filled = limit;
|
||||||
|
}
|
||||||
|
res = memchr(p, rsptr[0], (filled - n + 1));
|
||||||
if (!res) {
|
if (!res) {
|
||||||
n = gz->z.buf_filled + 1;
|
n = filled;
|
||||||
|
if (limit > 0 && filled >= limit) break;
|
||||||
|
n++;
|
||||||
} else {
|
} else {
|
||||||
n += (long)(res - p);
|
n += (long)(res - p);
|
||||||
p = res;
|
p = res;
|
||||||
|
@ -3421,6 +3490,9 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
||||||
p++, n++;
|
p++, n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (maxlen > 1 && n == limit && (gz->z.buf_filled > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
|
||||||
|
n = gzreader_charboundary(gz, n);
|
||||||
|
}
|
||||||
|
|
||||||
gz->lineno++;
|
gz->lineno++;
|
||||||
dst = gzfile_read(gz, n);
|
dst = gzfile_read(gz, n);
|
||||||
|
|
|
@ -588,6 +588,40 @@ if defined? Zlib
|
||||||
Zlib::GzipReader.open(t.path) do |f|
|
Zlib::GzipReader.open(t.path) do |f|
|
||||||
assert_equal("foo\nbar\nbaz\n", f.gets(nil))
|
assert_equal("foo\nbar\nbaz\n", f.gets(nil))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Zlib::GzipReader.open(t.path) do |f|
|
||||||
|
assert_equal("foo\n", f.gets(10))
|
||||||
|
assert_equal("ba", f.gets(2))
|
||||||
|
assert_equal("r\nb", f.gets(nil, 3))
|
||||||
|
assert_equal("az\n", f.gets(nil, 10))
|
||||||
|
assert_nil(f.gets)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_gets2
|
||||||
|
t = Tempfile.new("test_zlib_gzip_reader_gets2")
|
||||||
|
t.close
|
||||||
|
ustrs = %W"\u{3042 3044 3046}\n \u{304b 304d 304f}\n \u{3055 3057 3059}\n"
|
||||||
|
Zlib::GzipWriter.open(t.path) {|gz| gz.print(*ustrs) }
|
||||||
|
|
||||||
|
Zlib::GzipReader.open(t.path, encoding: "UTF-8") do |f|
|
||||||
|
assert_equal(ustrs[0], f.gets)
|
||||||
|
assert_equal(ustrs[1], f.gets)
|
||||||
|
assert_equal(ustrs[2], f.gets)
|
||||||
|
assert_nil(f.gets)
|
||||||
|
end
|
||||||
|
|
||||||
|
Zlib::GzipReader.open(t.path, encoding: "UTF-8") do |f|
|
||||||
|
assert_equal(ustrs.join(''), f.gets(nil))
|
||||||
|
end
|
||||||
|
|
||||||
|
Zlib::GzipReader.open(t.path, encoding: "UTF-8") do |f|
|
||||||
|
assert_equal(ustrs[0], f.gets(20))
|
||||||
|
assert_equal(ustrs[1][0,2], f.gets(5))
|
||||||
|
assert_equal(ustrs[1][2..-1]+ustrs[2][0,1], f.gets(nil, 5))
|
||||||
|
assert_equal(ustrs[2][1..-1], f.gets(nil, 20))
|
||||||
|
assert_nil(f.gets)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_readline
|
def test_readline
|
||||||
|
|
Загрузка…
Ссылка в новой задаче