diff --git a/mrbgems/mruby-regexp/mrblib/regexp.rb b/mrbgems/mruby-regexp/mrblib/regexp.rb index b50e221b3..84740d578 100644 --- a/mrbgems/mruby-regexp/mrblib/regexp.rb +++ b/mrbgems/mruby-regexp/mrblib/regexp.rb @@ -8,9 +8,7 @@ class Regexp @named_captures || {} end - def options - @flags.to_i - end + # options is implemented in C (internal flags -> Ruby constants conversion) def self.last_match(n = nil) md = $~ diff --git a/mrbgems/mruby-regexp/src/regexp.c b/mrbgems/mruby-regexp/src/regexp.c index 77c0fe4dd..d580880f8 100644 --- a/mrbgems/mruby-regexp/src/regexp.c +++ b/mrbgems/mruby-regexp/src/regexp.c @@ -253,6 +253,34 @@ regexp_source(mrb_state *mrb, mrb_value self) return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@source")); } +/* + * Regexp#options - convert internal flags to Ruby constants + * Internal: IGNORECASE=1, MULTILINE=2, DOTALL=4, EXTENDED=8 + * Ruby: IGNORECASE=1, EXTENDED=2, MULTILINE=4 + */ +static mrb_value +regexp_options(mrb_state *mrb, mrb_value self) +{ + mrb_value flags_val = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@flags")); + uint32_t iflags = mrb_nil_p(flags_val) ? 0 : (uint32_t)mrb_integer(flags_val); + mrb_int opts = 0; + if (iflags & RE_FLAG_IGNORECASE) opts |= 1; /* Regexp::IGNORECASE */ + if (iflags & RE_FLAG_EXTENDED) opts |= 2; /* Regexp::EXTENDED */ + if (iflags & RE_FLAG_MULTILINE) opts |= 4; /* Regexp::MULTILINE */ + return mrb_fixnum_value(opts); +} + +/* + * Regexp#casefold? + */ +static mrb_value +regexp_casefold_p(mrb_state *mrb, mrb_value self) +{ + mrb_value flags_val = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@flags")); + uint32_t iflags = mrb_nil_p(flags_val) ? 0 : (uint32_t)mrb_integer(flags_val); + return mrb_bool_value((iflags & RE_FLAG_IGNORECASE) != 0); +} + /* * Regexp#to_s - CRuby-compatible (?flags:source) format */ @@ -574,6 +602,8 @@ mrb_mruby_regexp_gem_init(mrb_state *mrb) mrb_define_method(mrb, re, "==", regexp_eql, MRB_ARGS_REQ(1)); mrb_define_method(mrb, re, "eql?", regexp_eql, MRB_ARGS_REQ(1)); mrb_define_method(mrb, re, "hash", regexp_hash, MRB_ARGS_NONE()); + mrb_define_method(mrb, re, "options", regexp_options, MRB_ARGS_NONE()); + mrb_define_method(mrb, re, "casefold?", regexp_casefold_p, MRB_ARGS_NONE()); /* MatchData class */ struct RClass *md = mrb_define_class(mrb, "MatchData", mrb->object_class); diff --git a/mrbgems/mruby-regexp/test/regexp.rb b/mrbgems/mruby-regexp/test/regexp.rb index 58abf2ff4..4cabb883d 100644 --- a/mrbgems/mruby-regexp/test/regexp.rb +++ b/mrbgems/mruby-regexp/test/regexp.rb @@ -149,6 +149,22 @@ assert("Regexp#hash") do assert_not_equal r1.hash, r3.hash end +assert("Regexp#options") do + assert_equal 0, Regexp.new("abc").options + assert_equal Regexp::IGNORECASE, Regexp.new("abc", Regexp::IGNORECASE).options + assert_equal Regexp::MULTILINE, Regexp.new("abc", Regexp::MULTILINE).options + assert_equal Regexp::EXTENDED, Regexp.new("abc", Regexp::EXTENDED).options + assert_equal Regexp::IGNORECASE | Regexp::MULTILINE, + Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE).options + assert_equal Regexp::IGNORECASE | Regexp::EXTENDED | Regexp::MULTILINE, + Regexp.new("abc", Regexp::IGNORECASE | Regexp::EXTENDED | Regexp::MULTILINE).options +end + +assert("Regexp#casefold?") do + assert_true Regexp.new("abc", Regexp::IGNORECASE).casefold? + assert_false Regexp.new("abc").casefold? +end + assert("Regexp extended mode (x flag)") do # whitespace is ignored re = Regexp.new('a b c', Regexp::EXTENDED)