From b8fde968619cb9116fb765c70b3295460645652f Mon Sep 17 00:00:00 2001 From: naruse Date: Wed, 18 May 2016 04:56:02 +0000 Subject: * re.c (match_ary_subseq): get subseq of match array without creating temporary array. * re.c (match_ary_aref): get element(s) of match array without creating temporary array. * re.c (match_aref): Use match_ary_subseq with handling irregulars. * re.c (match_values_at): Use match_ary_aref. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 +++++++ re.c | 94 ++++++++++++++++++++++++++++++++++-------------- test/ruby/test_regexp.rb | 27 ++++++++++++-- 3 files changed, 105 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5663cf3774..9ff19d227d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Wed May 18 13:11:44 2016 NARUSE, Yui + + * re.c (match_ary_subseq): get subseq of match array without creating + temporary array. + + * re.c (match_ary_aref): get element(s) of match array without creating + temporary array. + + * re.c (match_aref): Use match_ary_subseq with handling irregulars. + + * re.c (match_values_at): Use match_ary_aref. + Wed May 18 13:03:07 2016 Kazuki Yamaguchi * ext/openssl/ossl_x509cert.c (ossl_x509_verify): X509_verify() diff --git a/re.c b/re.c index ae8e2caf05..a48f23a3ca 100644 --- a/re.c +++ b/re.c @@ -1851,6 +1851,42 @@ namev_to_backref_number(struct re_registers *regs, VALUE re, VALUE name) } } +static VALUE +match_ary_subseq(VALUE match, long beg, long len, VALUE result) +{ + long olen = RMATCH_REGS(match)->num_regs; + long j, end = olen < beg+len ? olen : beg+len; + if (NIL_P(result)) result = rb_ary_new_capa(len); + if (len == 0) return result; + + for (j = beg; j < end; j++) { + rb_ary_push(result, rb_reg_nth_match((int)j, match)); + } + if (beg + len > j) { + rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j); + } + return result; +} + +static VALUE +match_ary_aref(VALUE match, VALUE idx, VALUE result) +{ + long beg, len; + int num_regs = RMATCH_REGS(match)->num_regs; + + /* check if idx is Range */ + switch (rb_range_beg_len(idx, &beg, &len, (long)num_regs, !NIL_P(result))) { + case Qfalse: + if (NIL_P(result)) return rb_reg_nth_match(NUM2INT(idx), match); + rb_ary_push(result, rb_reg_nth_match(NUM2INT(idx), match)); + return result; + case Qnil: + return Qnil; + default: + return match_ary_subseq(match, beg, len, result); + } +} + /* * call-seq: * mtch[i] -> str or nil @@ -1881,12 +1917,12 @@ namev_to_backref_number(struct re_registers *regs, VALUE re, VALUE name) static VALUE match_aref(int argc, VALUE *argv, VALUE match) { - VALUE idx, rest; + VALUE idx, length; match_check(match); - rb_scan_args(argc, argv, "11", &idx, &rest); + rb_scan_args(argc, argv, "11", &idx, &length); - if (NIL_P(rest)) { + if (NIL_P(length)) { if (FIXNUM_P(idx)) { return rb_reg_nth_match(FIX2INT(idx), match); } @@ -1895,10 +1931,30 @@ match_aref(int argc, VALUE *argv, VALUE match) if (num >= 0) { return rb_reg_nth_match(num, match); } + else { + return match_ary_aref(match, idx, Qnil); + } } } - - return rb_ary_aref(argc, argv, match_to_a(match)); + else { + long beg = NUM2LONG(idx); + long len = NUM2LONG(length); + long num_regs = RMATCH_REGS(match)->num_regs; + if (len < 0) { + return Qnil; + } + if (beg < 0) { + beg += num_regs; + if (beg < 0) return Qnil; + } + else if (beg > num_regs) { + return Qnil; + } + else if (beg+len > num_regs) { + len = num_regs - beg; + } + return match_ary_subseq(match, beg, len, Qnil); + } } /* @@ -1921,7 +1977,6 @@ match_aref(int argc, VALUE *argv, VALUE match) static VALUE match_values_at(int argc, VALUE *argv, VALUE match) { - struct re_registers *regs = RMATCH_REGS(match); VALUE result; int i; @@ -1929,31 +1984,18 @@ match_values_at(int argc, VALUE *argv, VALUE match) result = rb_ary_new2(argc); for (i=0; iregexp, argv[i]); - if (num >= 0) { - rb_ary_push(result, rb_reg_nth_match(num, match)); - continue; } - /* check if idx is Range */ - olen = regs->num_regs; - if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) { - long j, end = olen < beg+len ? olen : beg+len; - for (j = beg; j < end; j++) { - rb_ary_push(result, rb_reg_nth_match((int)j, match)); + else { + int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, argv[i]); + if (num >= 0) { + rb_ary_push(result, rb_reg_nth_match(num, match)); + } + else { + match_ary_aref(match, argv[i], result); } - if (beg + len > j) - rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j); - continue; } - tmp = rb_to_int(argv[i]); - rb_ary_push(result, rb_reg_nth_match(NUM2INT(tmp), match)); } return result; } diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index a8a120cf3f..0562785199 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -374,23 +374,46 @@ class TestRegexp < Test::Unit::TestCase def test_match_aref m = /(...)(...)(...)(...)?/.match("foobarbaz") + assert_equal("foobarbaz", m[0]) assert_equal("foo", m[1]) + assert_equal("foo", m[-4]) + assert_nil(m[-1]) + assert_nil(m[-11]) + assert_nil(m[-11, 1]) + assert_nil(m[-11..1]) + assert_nil(m[5]) + assert_nil(m[9]) assert_equal(["foo", "bar", "baz"], m[1..3]) + assert_equal(["foo", "bar", "baz"], m[1, 3]) + assert_equal([], m[3..1]) + assert_equal([], m[3, 0]) + assert_equal(nil, m[3, -1]) + assert_equal(nil, m[9, 1]) + assert_equal(["baz"], m[3, 1]) + assert_equal(["baz", nil], m[3, 5]) assert_nil(m[5]) assert_raise(IndexError) { m[:foo] } + assert_raise(TypeError) { m[nil] } end def test_match_values_at + idx = Object.new + def idx.to_int; 2; end m = /(...)(...)(...)(...)?/.match("foobarbaz") assert_equal(["foo", "bar", "baz"], m.values_at(1, 2, 3)) assert_equal(["foo", "bar", "baz"], m.values_at(1..3)) + assert_equal(["foo", "bar", "baz", nil, nil], m.values_at(1..5)) + assert_equal([], m.values_at(3..1)) + assert_equal([nil, nil, nil, nil, nil], m.values_at(5..9)) + assert_equal(["bar"], m.values_at(idx)) + assert_raise(RangeError){ m.values_at(-11..1) } + assert_raise(TypeError){ m.values_at(nil) } m = /(?\d+) *(?[+\-*\/]) *(?\d+)/.match("1 + 2") assert_equal(["1", "2", "+"], m.values_at(:a, 'b', :op)) - idx = Object.new - def idx.to_int; 2; end assert_equal(["+"], m.values_at(idx)) assert_raise(TypeError){ m.values_at(nil) } + assert_raise(IndexError){ m.values_at(:foo) } end def test_match_string -- cgit v1.2.3