зеркало из 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
|
||||
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);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
gzfile_read(struct gzfile *gz, long len)
|
||||
static long
|
||||
gzfile_fill(struct gzfile *gz, long len)
|
||||
{
|
||||
VALUE dst;
|
||||
|
||||
if (len < 0)
|
||||
rb_raise(rb_eArgError, "negative length %ld given", len);
|
||||
if (len == 0)
|
||||
return rb_str_new(0, 0);
|
||||
return 0;
|
||||
while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
|
||||
gzfile_read_more(gz);
|
||||
}
|
||||
|
@ -2220,9 +2218,19 @@ gzfile_read(struct gzfile *gz, long len)
|
|||
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
|
||||
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);
|
||||
gzfile_calc_crc(gz, dst);
|
||||
return dst;
|
||||
|
@ -3351,6 +3359,27 @@ rscheck(const char *rsptr, long rslen, VALUE rs)
|
|||
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
|
||||
gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
||||
{
|
||||
|
@ -3359,24 +3388,57 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
|||
VALUE dst;
|
||||
const char *rsptr;
|
||||
char *p, *res;
|
||||
long rslen, n;
|
||||
long rslen, n, limit = -1;
|
||||
int rspara;
|
||||
rb_encoding *enc = gz->enc;
|
||||
int maxlen = rb_enc_mbmaxlen(enc);
|
||||
|
||||
if (argc == 0) {
|
||||
rs = rb_rs;
|
||||
}
|
||||
else {
|
||||
rb_scan_args(argc, argv, "1", &rs);
|
||||
if (!NIL_P(rs)) {
|
||||
Check_Type(rs, T_STRING);
|
||||
VALUE lim, tmp;
|
||||
|
||||
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)) {
|
||||
dst = gzfile_read_all(gz);
|
||||
if (RSTRING_LEN(dst) != 0) gz->lineno++;
|
||||
else
|
||||
if (limit < 0) {
|
||||
dst = gzfile_read_all(gz);
|
||||
if (RSTRING_LEN(dst) == 0) return Qnil;
|
||||
}
|
||||
else if ((n = gzfile_fill(gz, limit)) <= 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);
|
||||
gzfile_calc_crc(gz, dst);
|
||||
dst = gzfile_newstr(gz, dst);
|
||||
}
|
||||
gz->lineno++;
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
@ -3405,15 +3467,22 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
|||
p = RSTRING_PTR(gz->z.buf);
|
||||
n = rslen;
|
||||
for (;;) {
|
||||
long filled;
|
||||
if (n > gz->z.buf_filled) {
|
||||
if (ZSTREAM_IS_FINISHED(&gz->z)) break;
|
||||
gzfile_read_more(gz);
|
||||
p = RSTRING_PTR(gz->z.buf) + n - rslen;
|
||||
}
|
||||
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) {
|
||||
n = gz->z.buf_filled + 1;
|
||||
n = filled;
|
||||
if (limit > 0 && filled >= limit) break;
|
||||
n++;
|
||||
} else {
|
||||
n += (long)(res - p);
|
||||
p = res;
|
||||
|
@ -3421,6 +3490,9 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
|
|||
p++, n++;
|
||||
}
|
||||
}
|
||||
if (maxlen > 1 && n == limit && (gz->z.buf_filled > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
|
||||
n = gzreader_charboundary(gz, n);
|
||||
}
|
||||
|
||||
gz->lineno++;
|
||||
dst = gzfile_read(gz, n);
|
||||
|
|
|
@ -588,6 +588,40 @@ if defined? Zlib
|
|||
Zlib::GzipReader.open(t.path) do |f|
|
||||
assert_equal("foo\nbar\nbaz\n", f.gets(nil))
|
||||
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
|
||||
|
||||
def test_readline
|
||||
|
|
Загрузка…
Ссылка в новой задаче