[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]