From f09574c879fe9a4488164a41b453617b4b1d56bb Mon Sep 17 00:00:00 2001 From: naruse Date: Wed, 18 May 2016 10:37:13 +0000 Subject: * re.c (rb_reg_match_m_p): Introduce Regexp#match?, which returns bool and doesn't save backref. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55061 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 ++++ NEWS | 5 ++++ re.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ test/ruby/test_regexp.rb | 13 +++++++++ 4 files changed, 98 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4cea47b666..b5d1e8f8c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed May 18 19:33:54 2016 NARUSE, Yui + + * re.c (rb_reg_match_m_p): Introduce Regexp#match?, which returns + bool and doesn't save backref. + Wed May 18 16:52:03 2016 Kazuki Yamaguchi * ext/openssl/ossl_pkcs12.c (ossl_pkcs12_initialize): pop errors diff --git a/NEWS b/NEWS index 0d1d7820e6..8915f96f58 100644 --- a/NEWS +++ b/NEWS @@ -54,6 +54,11 @@ with all sufficient information, see the ChangeLog file or Redmine * Fixnum and Bignum are unified into Integer [Feature #12005] +* Regexp + + * Regexp#match? [Feature #8110] + This returns bool and doesn't save backref. + * String * String.new(capacity: size) [Feature #12024] diff --git a/re.c b/re.c index a48f23a3ca..aa92c0dc29 100644 --- a/re.c +++ b/re.c @@ -3202,6 +3202,80 @@ rb_reg_match_m(int argc, VALUE *argv, VALUE re) return result; } +/* + * call-seq: + * rxp.match?(str) -> true or false + * rxp.match?(str,pos) -> true or false + * + * Returns a true or false indicates whether the + * regexp is matched or not without updating $~ and other related variables. + * If the second parameter is present, it specifies the position in the string + * to begin the search. + * + * /R.../.match?("Ruby") #=> true + * /R.../.match?("Ruby", 1) #=> true + * /P.../.match?("Ruby") #=> false + * $& #=> nil + */ + +static VALUE +rb_reg_match_m_p(int argc, VALUE *argv, VALUE re) +{ + VALUE str, initpos; + long pos = 0; + regex_t *reg; + onig_errmsg_buffer err = ""; + int result, tmpreg; + + rb_scan_args(argc, argv, "11", &str, &initpos); + if (NIL_P(str)) return Qnil; + str = SYMBOL_P(str) ? rb_sym2str(str) : rb_str_to_str(str); + if (argc == 2) { + pos = NUM2LONG(initpos); + if (pos == 0) goto run; + if (pos < 0) { + pos += NUM2LONG(rb_str_length(str)); + if (pos == 0) goto run; + if (pos < 0) return Qnil; + + } + pos = rb_str_offset(str, pos); + } +run: + if (pos >= RSTRING_LEN(str)) { + return Qnil; + } + reg = rb_reg_prepare_re0(re, str, err); + tmpreg = reg != RREGEXP_PTR(re); + if (!tmpreg) RREGEXP(re)->usecnt++; + result = onig_search(reg, + ((UChar*)RSTRING_PTR(str)), + ((UChar*)RSTRING_END(str)), + ((UChar*)(RSTRING_PTR(str)) + pos), + ((UChar*)RSTRING_PTR(str)), + NULL, ONIG_OPTION_NONE); + if (!tmpreg) RREGEXP(re)->usecnt--; + if (tmpreg) { + if (RREGEXP(re)->usecnt) { + onig_free(reg); + } + else { + onig_free(RREGEXP_PTR(re)); + RREGEXP_PTR(re) = reg; + } + } + if (result < 0) { + if (result == ONIG_MISMATCH) { + return Qfalse; + } + else { + onig_error_code_to_str((UChar*)err, (int)result); + rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re); + } + } + return Qtrue; +} + /* * Document-method: compile * @@ -3865,6 +3939,7 @@ Init_Regexp(void) rb_define_method(rb_cRegexp, "===", rb_reg_eqq, 1); rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0); rb_define_method(rb_cRegexp, "match", rb_reg_match_m, -1); + rb_define_method(rb_cRegexp, "match?", rb_reg_match_m_p, -1); rb_define_method(rb_cRegexp, "to_s", rb_reg_to_s, 0); rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0); rb_define_method(rb_cRegexp, "source", rb_reg_source, 0); diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 0562785199..4d534114da 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -526,6 +526,19 @@ class TestRegexp < Test::Unit::TestCase $_ = nil; assert_nil(~/./) end + def test_match_p + /backref/ =~ 'backref' + assert_nil(//.match?(nil)) + assert_equal(true, /.../.match?(:abc)) + assert_raise(TypeError) { /.../.match?(Object.new) } + assert_equal(true, /../.match?('abc', 1)) + assert_equal(true, /../.match?('abc', -2)) + assert_nil(/../.match?("abc", -4)) + assert_nil(/../.match?("abc", 4)) + assert_equal(true, /../n.match?("\u3042" + '\x', 1)) + assert_equal('backref', $&) + end + def test_eqq assert_equal(false, /../ === nil) end -- cgit v1.2.3