Created
April 28, 2013 14:13
-
-
Save rkh/5477001 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c | |
| index b81e1f1..2475ba5 100644 | |
| --- a/ext/strscan/strscan.c | |
| +++ b/ext/strscan/strscan.c | |
| @@ -38,6 +38,9 @@ struct strscanner | |
| /* 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) | |
| @@ -445,17 +448,36 @@ strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly) | |
| { | |
| regex_t *rb_reg_prepare_re(VALUE re, VALUE str); | |
| struct strscanner *p; | |
| - regex_t *re; | |
| + regex_t *re, *oldre; | |
| long ret; | |
| - int tmpreg; | |
| + int tmpreg, oldtmpreg; | |
| Check_Type(regex, T_REGEXP); | |
| GET_SCANNER(self, p); | |
| + // THIS SEGFAULTS | |
| + // if (p->regex) { | |
| + // oldre = rb_reg_prepare_re(regex, p->str); | |
| + // oldtmpreg = oldre != RREGEXP(p->regex)->ptr; | |
| + // if (oldtmpreg) { | |
| + // if (RREGEXP(p->regex)->usecnt) { | |
| + // onig_free(oldre); | |
| + // } | |
| + // else { | |
| + // onig_free(RREGEXP(p->regex)->ptr); | |
| + // RREGEXP(p->regex)->ptr = oldre; | |
| + // } | |
| + // } else { | |
| + // RREGEXP(p->regex)->usecnt--; | |
| + // } | |
| + // } | |
| + | |
| CLEAR_MATCH_STATUS(p); | |
| 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++; | |
| @@ -471,16 +493,6 @@ strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly) | |
| (UChar* )CURPTR(p), (UChar* )(CURPTR(p) + S_RESTLEN(p)), | |
| &(p->regs), ONIG_OPTION_NONE); | |
| } | |
| - if (!tmpreg) RREGEXP(regex)->usecnt--; | |
| - if (tmpreg) { | |
| - if (RREGEXP(regex)->usecnt) { | |
| - onig_free(re); | |
| - } | |
| - else { | |
| - onig_free(RREGEXP(regex)->ptr); | |
| - RREGEXP(regex)->ptr = re; | |
| - } | |
| - } | |
| if (ret == -2) rb_raise(ScanError, "regexp buffer overflow"); | |
| if (ret < 0) { | |
| @@ -976,11 +988,14 @@ strscan_matched_size(VALUE self) | |
| * 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 # -> "" | |
| */ | |
| @@ -993,7 +1008,16 @@ strscan_aref(VALUE self, VALUE idx) | |
| GET_SCANNER(self, p); | |
| if (! MATCHED_P(p)) return Qnil; | |
| - i = NUM2LONG(idx); | |
| + if (TYPE(idx) == T_SYMBOL) { | |
| + const char *name, *name_end; | |
| + name = rb_id2name(SYM2ID(idx)); | |
| + 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)); | |
| + } else { | |
| + i = NUM2LONG(idx); | |
| + } | |
| + | |
| if (i < 0) | |
| i += p->regs.num_regs; | |
| if (i < 0) return Qnil; | |
| diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb | |
| index 2c4cf90..c1c356e 100644 | |
| --- a/test/strscan/test_stringscanner.rb | |
| +++ b/test/strscan/test_stringscanner.rb | |
| @@ -457,6 +457,14 @@ class TestStringScanner < Test::Unit::TestCase | |
| 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] | |
| end | |
| def test_pre_match |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment