Feature #8343 ยป 0001-make-StringScanner-accept-names-of-named-captures.patch
| ext/strscan/strscan.c | ||
|---|---|---|
|     /* 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) | ||
| ... | ... | |
|     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++; | ||
| ... | ... | |
|  * Return the n-th subgroup in the most recent match. | ||
|  * | ||
|  *   s = StringScanner.new("Fri Dec 12 1975 14:39") | ||
|  *   s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 " | ||
|  *   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; | ||
| test/strscan/test_stringscanner.rb | ||
|---|---|---|
|     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 | ||