From: Tanaka Akira Date: 2008-02-15T00:04:09+09:00 Subject: [ruby-dev:33784] MatchData#{key?,has_key?} MatchData で、ある部分文字列が存在するかどうかを調べる MatchData#has_key?(n), MatchData#key?(n) を追加するのはどう でしょうか。 これがなくても MatchData#[n] で調べられますが、これは文字列を 生成するので効率上嬉しくありません。 1.8 では MatchData#begin(n) が使えたのですが、これは 1.9 で 文字列の長さに比例した時間がかかるようになっているので使えま せん。 Index: re.c =================================================================== --- re.c (revision 15432) +++ re.c (working copy) @@ -1396,6 +1396,40 @@ match_aref(int argc, VALUE *argv, VALUE } static VALUE +match_has_key(VALUE match, VALUE idx) +{ + int nth; + VALUE name, regexp; + + if (FIXNUM_P(idx)) { + nth = FIX2INT(idx); + } + else { + if (TYPE(idx) == T_SYMBOL) + name = rb_id2str(SYM2ID(idx)); + else + name = StringValue(idx); + regexp = RMATCH(match)->regexp; + nth = onig_name_to_backref_number(RREGEXP(regexp)->ptr, + (const unsigned char*)RSTRING_PTR(name), + (const unsigned char*)RSTRING_PTR(name) + RSTRING_LEN(name), + RMATCH(match)->regs); + if (nth < 1) + return Qnil; + } + if (nth >= RMATCH(match)->regs->num_regs) { + return Qnil; + } + if (nth < 0) { + nth += RMATCH(match)->regs->num_regs; + if (nth <= 0) return Qnil; + } + if (RMATCH(match)->BEG(nth) == -1) + return Qfalse; + return Qtrue; +} + +static VALUE match_entry(VALUE match, long n) { return rb_reg_nth_match(n, match); @@ -3104,6 +3138,8 @@ Init_Regexp(void) rb_define_method(rb_cMatch, "end", match_end, 1); rb_define_method(rb_cMatch, "to_a", match_to_a, 0); rb_define_method(rb_cMatch, "[]", match_aref, -1); + rb_define_method(rb_cMatch, "has_key?", match_has_key, 1); + rb_define_method(rb_cMatch, "key?", match_has_key, 1); rb_define_method(rb_cMatch, "captures", match_captures, 0); rb_define_method(rb_cMatch, "values_at", match_values_at, -1); rb_define_method(rb_cMatch, "select", match_values_at, -1); -- [田中 哲][たなか あきら][Tanaka Akira]