Project

General

Profile

11999-2.diff

Based on specification at [ruby-core:73839] - sorah (Sorah Fukumori), 02/16/2016 12:35 PM

View differences:

re.c
1937 1937
    return str;
1938 1938
}
1939 1939

  
1940
static int
1941
match_named_captures_iter(const OnigUChar *name, const OnigUChar *name_end,
1942
	int back_num, int *back_refs, OnigRegex regex, void *arg) {
1943
    struct MEMO *memo = MEMO_CAST(arg);
1944
    VALUE hash = memo->v1;
1945
    VALUE match = memo->v2;
1946

  
1947
    VALUE key = rb_enc_str_new((const char *)name, name_end-name, regex->enc);
1948
    VALUE value;
1949

  
1950
    int i;
1951
    int found = 0;
1952

  
1953
    for (i = 0; i < back_num; i++) {
1954
	value = rb_reg_nth_match(back_refs[i], match);
1955
	if (RTEST(value)) {
1956
	    rb_hash_aset(hash, key, value);
1957
	    found = 1;
1958
	}
1959
    }
1960

  
1961
    if (found == 0) {
1962
	rb_hash_aset(hash, key, Qnil);
1963
    }
1964

  
1965
    return 0;
1966
}
1967

  
1968
/*
1969
 *  call-seq:
1970
 *     mtch.named_captures -> hash
1971
 *
1972
 *  Returns a Hash using named capture.
1973
 *
1974
 *  A key of the hash is a name of the named captures.
1975
 *  A value of the hash is a string of last successful capture of corresponding
1976
 *  group.
1977
 *
1978
 *     m = /(?<a>.)(?<b>.)/.match("01")
1979
 *     m.named_captures #=> {"a" => "0", "b" => "1"}
1980
 *
1981
 *     m = /(?<a>.)(?<b>.)?/.match("0")
1982
 *     m.named_captures #=> {"a" => "0", "b" => nil}
1983
 *
1984
 *     m = /(?<a>.)(?<a>.)/.match("01")
1985
 *     m.named_captures #=> {"a" => "1"}
1986
 *
1987
 *     m = /(?<a>x)|(?<a>y)/.match("x")
1988
 *     m.named_captures #=> {"a" => "x"}
1989
 */
1990

  
1991
static VALUE
1992
match_named_captures(VALUE match)
1993
{
1994
    VALUE hash;
1995
    struct MEMO *memo;
1996

  
1997
    match_check(match);
1998

  
1999
    hash = rb_hash_new();
2000
    memo = MEMO_NEW(hash, match, 0);
2001

  
2002
    onig_foreach_name(RREGEXP(RMATCH(match)->regexp)->ptr, match_named_captures_iter, (void*)memo);
2003

  
2004
    return hash;
2005
}
1940 2006

  
1941 2007
/*
1942 2008
 *  call-seq:
......
3751 3817
    rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
3752 3818
    rb_define_method(rb_cMatch, "[]", match_aref, -1);
3753 3819
    rb_define_method(rb_cMatch, "captures", match_captures, 0);
3820
    rb_define_method(rb_cMatch, "named_captures", match_named_captures, 0);
3754 3821
    rb_define_method(rb_cMatch, "values_at", match_values_at, -1);
3755 3822
    rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
3756 3823
    rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
test/ruby/test_regexp.rb
175 175
    assert_raise(IndexError, bug9903) {m[key.dup.force_encoding(Encoding::Shift_JIS)]}
176 176
  end
177 177

  
178
  def test_match_data_named_captures
179
    assert_equal({'a' => '1', 'b' => '2', 'c' => nil}, /^(?<a>.)(?<b>.)(?<c>.)?/.match('12').named_captures)
180
    assert_equal({'a' => '1', 'b' => '2', 'c' => '3'}, /^(?<a>.)(?<b>.)(?<c>.)?/.match('123').named_captures)
181
    assert_equal({'a' => '1', 'b' => '2', 'c' => ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures)
182

  
183
    assert_equal({'a' => 'x'}, /(?<a>x)|(?<a>y)/.match('x').named_captures)
184
    assert_equal({'a' => 'y'}, /(?<a>x)|(?<a>y)/.match('y').named_captures)
185

  
186
    assert_equal({'a' => '1', 'b' => '2'}, /^(.)(?<a>.)(?<b>.)/.match('012').named_captures)
187
    assert_equal({'a' => '2'}, /^(?<a>.)(?<a>.)/.match('12').named_captures)
188

  
189
    assert_equal({}, /^(.)/.match('123').named_captures)
190
  end
191

  
178 192
  def test_assign_named_capture
179 193
    assert_equal("a", eval('/(?<foo>.)/ =~ "a"; foo'))
180 194
    assert_equal(nil, eval('/(?<@foo>.)/ =~ "a"; defined?(@foo)'))