mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-regexp: fix Regexp#options to return Ruby constant values
Internal flags (MULTILINE=2, DOTALL=4, EXTENDED=8) differ from Ruby constants (EXTENDED=2, MULTILINE=4). Convert in C instead of returning raw internal flags. Also add Regexp#casefold?. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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 = $~
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user