ruby-changes:44980
From: nobu <ko1@a...>
Date: Mon, 12 Dec 2016 11:56:17 +0900 (JST)
Subject: [ruby-changes:44980] nobu:r57053 (trunk): String#match? and Symbol#match?
nobu 2016-12-12 11:56:12 +0900 (Mon, 12 Dec 2016) New Revision: 57053 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=57053 Log: String#match? and Symbol#match? * string.c (rb_str_match_m_p): inverse of Regexp#match?. based on the patch by Herwin Weststrate <herwin@s...>. [Fix GH-1483] [Feature #12898] Modified files: trunk/internal.h trunk/re.c trunk/string.c trunk/test/ruby/test_string.rb Index: internal.h =================================================================== --- internal.h (revision 57052) +++ internal.h (revision 57053) @@ -1394,6 +1394,7 @@ VALUE rb_rational_cmp(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/internal.h#L1394 VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline); VALUE rb_reg_check_preprocess(VALUE); long rb_reg_search0(VALUE, VALUE, long, int, int); +VALUE rb_reg_match_p(VALUE re, VALUE str, long pos); void rb_backref_set_string(VALUE string, long pos, long len); int rb_match_count(VALUE match); int rb_match_nth_defined(int nth, VALUE match); Index: test/ruby/test_string.rb =================================================================== --- test/ruby/test_string.rb (revision 57052) +++ test/ruby/test_string.rb (revision 57053) @@ -2111,6 +2111,50 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L2111 assert_raise(ArgumentError) { "foo".match } end + def test_match_p_regexp + /backref/ =~ 'backref' + # must match here, but not in a separate method, e.g., assert_send, + # to check if $~ is affected or not. + assert_equal(true, "".match?(//)) + assert_equal(true, :abc.match?(/.../)) + assert_equal(true, 'abc'.match?(/b/)) + assert_equal(true, 'abc'.match?(/b/, 1)) + assert_equal(true, 'abc'.match?(/../, 1)) + assert_equal(true, 'abc'.match?(/../, -2)) + assert_equal(false, 'abc'.match?(/../, -4)) + assert_equal(false, 'abc'.match?(/../, 4)) + assert_equal(true, "\u3042xx".match?(/../, 1)) + assert_equal(false, "\u3042x".match?(/../, 1)) + assert_equal(true, ''.match?(/\z/)) + assert_equal(true, 'abc'.match?(/\z/)) + assert_equal(true, 'Ruby'.match?(/R.../)) + assert_equal(false, 'Ruby'.match?(/R.../, 1)) + assert_equal(false, 'Ruby'.match?(/P.../)) + assert_equal('backref', $&) + end + + def test_match_p_string + /backref/ =~ 'backref' + # must match here, but not in a separate method, e.g., assert_send, + # to check if $~ is affected or not. + assert_equal(true, "".match?('')) + assert_equal(true, :abc.match?('...')) + assert_equal(true, 'abc'.match?('b')) + assert_equal(true, 'abc'.match?('b', 1)) + assert_equal(true, 'abc'.match?('..', 1)) + assert_equal(true, 'abc'.match?('..', -2)) + assert_equal(false, 'abc'.match?('..', -4)) + assert_equal(false, 'abc'.match?('..', 4)) + assert_equal(true, "\u3042xx".match?('..', 1)) + assert_equal(false, "\u3042x".match?('..', 1)) + assert_equal(true, ''.match?('\z')) + assert_equal(true, 'abc'.match?('\z')) + assert_equal(true, 'Ruby'.match?('R...')) + assert_equal(false, 'Ruby'.match?('R...', 1)) + assert_equal(false, 'Ruby'.match?('P...')) + assert_equal('backref', $&) + end + def test_clear s = "foo" * 100 s.clear Index: re.c =================================================================== --- re.c (revision 57052) +++ re.c (revision 57053) @@ -3225,19 +3225,22 @@ rb_reg_match_m(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/re.c#L3225 static VALUE rb_reg_match_m_p(int argc, VALUE *argv, VALUE re) { - VALUE str, initpos; - long pos = 0; + long pos = rb_check_arity(argc, 1, 2) > 1 ? NUM2LONG(argv[1]) : 0; + return rb_reg_match_p(re, argv[0], pos); +} + +VALUE +rb_reg_match_p(VALUE re, VALUE str, long pos) +{ regex_t *reg; onig_errmsg_buffer err = ""; OnigPosition result; const UChar *start, *end; int tmpreg; - rb_scan_args(argc, argv, "11", &str, &initpos); if (NIL_P(str)) return Qfalse; - str = SYMBOL_P(str) ? rb_sym2str(str) : rb_str_to_str(str); - if (argc == 2) { - pos = NUM2LONG(initpos); + str = SYMBOL_P(str) ? rb_sym2str(str) : StringValue(str); + if (pos) { if (pos < 0) { pos += NUM2LONG(rb_str_length(str)); if (pos < 0) return Qfalse; Index: string.c =================================================================== --- string.c (revision 57052) +++ string.c (revision 57053) @@ -3601,6 +3601,32 @@ rb_str_match_m(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/string.c#L3601 return result; } +/* + * call-seq: + * str.match?(pattern) -> true or false + * str.match?(pattern, pos) -> true or false + * + * Converts _pattern_ to a +Regexp+ (if it isn't already one), then + * returns a +true+ or +false+ indicates whether the regexp is + * matched _str_ or not without updating <code>$~</code> and other + * related variables. If the second parameter is present, it + * specifies the position in the string to begin the search. + * + * "Ruby".match?(/R.../) #=> true + * "Ruby".match?(/R.../, 1) #=> false + * "Ruby".match?(/P.../) #=> false + * $& #=> nil + */ + +static VALUE +rb_str_match_m_p(int argc, VALUE *argv, VALUE str) +{ + VALUE re; + rb_check_arity(argc, 1, 2); + re = get_pat(argv[0]); + return rb_reg_match_p(re, str, argc > 1 ? NUM2LONG(argv[1]) : 0); +} + enum neighbor_char { NEIGHBOR_NOT_CHAR, NEIGHBOR_FOUND, @@ -9740,6 +9766,19 @@ sym_match_m(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/string.c#L9766 /* * call-seq: + * sym.match?(obj) -> true or false + * + * Returns <code>sym.to_s.match?(obj)</code>. + */ + +static VALUE +sym_match_m_p(int argc, VALUE *argv, VALUE sym) +{ + return rb_str_match_m_p(argc, argv, sym); +} + +/* + * call-seq: * sym[idx] -> char * sym[b, n] -> string * sym.slice(idx) -> char @@ -9924,6 +9963,7 @@ Init_String(void) https://github.com/ruby/ruby/blob/trunk/string.c#L9963 rb_define_method(rb_cString, "empty?", rb_str_empty, 0); rb_define_method(rb_cString, "=~", rb_str_match, 1); rb_define_method(rb_cString, "match", rb_str_match_m, -1); + rb_define_method(rb_cString, "match?", rb_str_match_m_p, -1); rb_define_method(rb_cString, "succ", rb_str_succ, 0); rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0); rb_define_method(rb_cString, "next", rb_str_succ, 0); @@ -10070,6 +10110,7 @@ Init_String(void) https://github.com/ruby/ruby/blob/trunk/string.c#L10110 rb_define_method(rb_cSymbol, "size", sym_length, 0); rb_define_method(rb_cSymbol, "empty?", sym_empty, 0); rb_define_method(rb_cSymbol, "match", sym_match_m, -1); + rb_define_method(rb_cSymbol, "match?", sym_match_m_p, -1); rb_define_method(rb_cSymbol, "upcase", sym_upcase, -1); rb_define_method(rb_cSymbol, "downcase", sym_downcase, -1); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/