ruby-changes:72256
From: Nobuyoshi <ko1@a...>
Date: Mon, 20 Jun 2022 19:35:32 +0900 (JST)
Subject: [ruby-changes:72256] 1e9939dae2 (master): [Feature #18788] Support options as `String` to `Regexp.new`
https://git.ruby-lang.org/ruby.git/commit/?id=1e9939dae2 From 1e9939dae24db232d6f3693630fa37a382e1a6d7 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 16 Jun 2022 18:53:35 +0900 Subject: [Feature #18788] Support options as `String` to `Regexp.new` `Regexp.new` now supports passing the regexp flags not only as an `Integer`, but also as a `String. Unknown flags raise errors. --- NEWS.md | 6 ++++-- re.c | 21 +++++++++++++++++++++ test/ruby/test_regexp.rb | 17 +++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 02163ff9c0..129cd45a1c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -119,8 +119,10 @@ Note: We're only listing outstanding class updates. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L119 * Proc#parameters now accepts lambda keyword. [[Feature #15357]] * Regexp - * Regexp.new now warns second argument, other than `true`, `false`, - `nil` or Integer. [[Feature #18788]] + * Regexp.new now supports passing the regexp flags not only as an Integer, + but also as a String Unknown flags raise errors. Otherwise, anything + other than `true`, `false`, `nil` or Integer will be warned. + [[Feature #18788]] * Refinement * Refinement#refined_class has been added. [[Feature #12737]] diff --git a/re.c b/re.c index f225a413d5..39d4fc046f 100644 --- a/re.c +++ b/re.c @@ -3632,6 +3632,25 @@ rb_reg_match_p(VALUE re, VALUE str, long pos) https://github.com/ruby/ruby/blob/trunk/re.c#L3632 * Alias for Regexp.new */ +static int +str_to_option(VALUE str) +{ + int flag = 0; + const char *ptr; + long len; + str = rb_check_string_type(str); + if (NIL_P(str)) return -1; + RSTRING_GETMEM(str, ptr, len); + for (long i = 0; i < len; ++i) { + int f = char_to_option(ptr[i]); + if (!f) { + rb_raise(rb_eArgError, "unknown regexp option: %"PRIsVALUE, str); + } + flag |= f; + } + return flag; +} + /* * call-seq: * Regexp.new(string, options = 0, n_flag = nil, timeout: nil) -> regexp @@ -3716,7 +3735,9 @@ rb_reg_initialize_m(int argc, VALUE *argv, VALUE self) https://github.com/ruby/ruby/blob/trunk/re.c#L3735 } else { if (opts != Qundef) { + int f; if (FIXNUM_P(opts)) flags = FIX2INT(opts); + else if ((f = str_to_option(opts)) >= 0) flags = f; else if (!NIL_P(opts) && rb_bool_expected(opts, "ignorecase", FALSE)) flags = ONIG_OPTION_IGNORECASE; } diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 5ee6b1b03c..1d93d1a5b1 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -634,6 +634,23 @@ class TestRegexp < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_regexp.rb#L634 end end + def test_initialize_option + assert_equal(//i, Regexp.new("", "i")) + assert_equal(//m, Regexp.new("", "m")) + assert_equal(//x, Regexp.new("", "x")) + assert_equal(//imx, Regexp.new("", "imx")) + assert_equal(//, Regexp.new("", "")) + assert_equal(//imx, Regexp.new("", "mimix")) + + assert_raise(ArgumentError) { Regexp.new("", "e") } + assert_raise(ArgumentError) { Regexp.new("", "n") } + assert_raise(ArgumentError) { Regexp.new("", "s") } + assert_raise(ArgumentError) { Regexp.new("", "u") } + assert_raise(ArgumentError) { Regexp.new("", "o") } + assert_raise(ArgumentError) { Regexp.new("", "j") } + assert_raise(ArgumentError) { Regexp.new("", "xmen") } + end + def test_match_control_meta_escape assert_equal(0, /\c\xFF/ =~ "\c\xFF") assert_equal(0, /\c\M-\xFF/ =~ "\c\M-\xFF") -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/