summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS.md6
-rw-r--r--re.c21
-rw-r--r--test/ruby/test_regexp.rb17
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.
* 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)
* 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;
}
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
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")