ruby-changes:28829
From: naruse <ko1@a...>
Date: Tue, 21 May 2013 22:49:08 +0900 (JST)
Subject: [ruby-changes:28829] naruse:r40881 (trunk): * ext/strscan/strscan.c (strscan_aref): support named captures.
naruse 2013-05-21 22:48:57 +0900 (Tue, 21 May 2013) New Revision: 40881 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40881 Log: * ext/strscan/strscan.c (strscan_aref): support named captures. patched by Konstantin Haase [ruby-core:54664] [Feature #8343] Modified files: trunk/ChangeLog trunk/ext/strscan/strscan.c trunk/test/strscan/test_stringscanner.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 40880) +++ ChangeLog (revision 40881) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue May 21 22:47:06 2013 NARUSE, Yui <naruse@r...> + + * ext/strscan/strscan.c (strscan_aref): support named captures. + patched by Konstantin Haase [ruby-core:54664] [Feature #8343] + Tue May 21 21:48:44 2013 Kouhei Sutou <kou@c...> * test/ruby/test_dir_m17n.rb (TestDir_M17N#test_entries_compose): Index: ext/strscan/strscan.c =================================================================== --- ext/strscan/strscan.c (revision 40880) +++ ext/strscan/strscan.c (revision 40881) @@ -38,6 +38,9 @@ struct strscanner https://github.com/ruby/ruby/blob/trunk/ext/strscan/strscan.c#L38 /* the regexp register; legal only when MATCHED_P(s) */ struct re_registers regs; + + /* regexp used for last scan */ + VALUE regex; }; #define MATCHED_P(s) ((s)->flags & FLAG_MATCHED) @@ -456,6 +459,8 @@ strscan_do_scan(VALUE self, VALUE regex, https://github.com/ruby/ruby/blob/trunk/ext/strscan/strscan.c#L459 if (S_RESTLEN(p) < 0) { return Qnil; } + + p->regex = regex; re = rb_reg_prepare_re(regex, p->str); tmpreg = re != RREGEXP(regex)->ptr; if (!tmpreg) RREGEXP(regex)->usecnt++; @@ -983,17 +988,45 @@ strscan_matched_size(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/strscan/strscan.c#L988 * s[3] # -> "12" * s.post_match # -> "1975 14:39" * s.pre_match # -> "" + * + * s.reset + * s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) # -> "Fri Dec 12 " + * s[0] # -> "Fri Dec 12 " + * s[1] # -> "Fri" + * s[2] # -> "Dec" + * s[3] # -> "12" + * s[:wday] # -> "Fri" + * s[:month] # -> "Dec" + * s[:day] # -> "12" + * s.post_match # -> "1975 14:39" + * s.pre_match # -> "" */ static VALUE strscan_aref(VALUE self, VALUE idx) { + const char *name, *name_end; struct strscanner *p; long i; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; - i = NUM2LONG(idx); + switch (TYPE(idx)) { + case T_SYMBOL: + name = rb_id2name(SYM2ID(idx)); + goto name_to_backref; + break; + case T_STRING: + name = StringValuePtr(idx); + name_to_backref: + name_end = name + strlen(name); + i = onig_name_to_backref_number(RREGEXP(p->regex)->ptr, + (const unsigned char* )name, (const unsigned char* )name_end, &(p->regs)); + break; + default: + i = NUM2LONG(idx); + } + if (i < 0) i += p->regs.num_regs; if (i < 0) return Qnil; Index: test/strscan/test_stringscanner.rb =================================================================== --- test/strscan/test_stringscanner.rb (revision 40880) +++ test/strscan/test_stringscanner.rb (revision 40881) @@ -457,6 +457,17 @@ class TestStringScanner < Test::Unit::Te https://github.com/ruby/ruby/blob/trunk/test/strscan/test_stringscanner.rb#L457 assert_equal true, s[2].tainted? assert_equal true, s[3].tainted? assert_equal true, s[4].tainted? + + s = StringScanner.new("foo bar") + s.scan /(?<a>(\w+)) (?<b>(\w+))/ + assert_equal 'foo', s[1] + assert_equal 'bar', s[2] + assert_equal 'foo', s[:a] + assert_equal 'bar', s[:b] + assert_equal nil, s[:c] + assert_equal 'foo', s['a'] + assert_equal 'bar', s['b'] + assert_equal nil, s['c'] end def test_pre_match -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/