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

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/

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