[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.
This commit is contained in:
Nobuyoshi Nakada 2022-06-16 18:53:35 +09:00
parent 39dc455b51
commit 1e9939dae2
Notes: git 2022-06-20 19:35:34 +09:00
3 changed files with 42 additions and 2 deletions

View File

@ -119,8 +119,10 @@ Note: We're only listing outstanding class updates.
* 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]]

21
re.c
View File

@ -3632,6 +3632,25 @@ rb_reg_match_p(VALUE re, VALUE str, long pos)
* 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)
}
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;
}

View File

@ -634,6 +634,23 @@ class TestRegexp < Test::Unit::TestCase
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")