Permalink
Browse files

Move ORegexp#=~ to C code, make it work just like Regexp#=~, i.e. set…

… $~. Throw ArgumentError instead of Exception if pattern does not compile
  • Loading branch information...
1 parent 18194f1 commit bcf193bcf9d7d52b80e1331eea3ca045135661dc Nikolai Lugovoi committed Mar 27, 2007
Showing with 51 additions and 19 deletions.
  1. +26 −1 ext/oregexp.c
  2. +0 −17 lib/oniguruma.rb
  3. +25 −1 test/test_oniguruma.rb
View
@@ -145,16 +145,18 @@ static VALUE oregexp_initialize( VALUE self, VALUE pattern, VALUE options ) {
if (r != ONIG_NORMAL) {
char s[ONIG_MAX_ERROR_MESSAGE_LEN];
onig_error_code_to_str(s, r, &einfo);
- rb_raise(rb_eException, "Oniguruma Error: %s", s);
+ rb_raise(rb_eArgError, "Oniguruma Error: %s", s);
}
return self;
}
+/* can't include re.h, since it conflicts with oniguruma typedefs */
struct RMatch {
struct RBasic basic;
VALUE str;
struct re_registers *regs;
};
+#define RMATCH(obj) (R_CAST(RMatch)(obj))
static VALUE oregexp_make_match_data(ORegexp * oregexp, OnigRegion * region, VALUE string_str) {
VALUE rb_cMatch = rb_const_get(rb_cObject, rb_intern("MatchData")) ;
@@ -203,9 +205,12 @@ static VALUE oregexp_match( VALUE self, VALUE string ) {
OnigRegion *region = onig_region_new();
int r = onig_search(oregexp->reg, str_ptr, str_ptr + str_len, str_ptr, str_ptr + str_len, region, ONIG_OPTION_NONE);
+ rb_backref_set(Qnil);
if (r >= 0) {
VALUE matchData = oregexp_make_match_data( oregexp, region, string_str);
onig_region_free(region, 1 );
+ rb_backref_set(matchData);
+ rb_match_busy(matchData);
return matchData;
} else if (r == ONIG_MISMATCH) {
onig_region_free(region, 1 );
@@ -444,6 +449,7 @@ oregexp_gsub(self, argc, argv, bang, once, region)
if ( iter ) {
VALUE match_data = oregexp_make_match_data( oregexp, region, string_str );
rb_backref_set(match_data);
+ rb_match_busy(match_data);
block_res = rb_yield( match_data );
str_mod_check( string_str, str_ptr, str_len);
curr_repl = rb_obj_as_string(block_res);
@@ -686,12 +692,31 @@ static VALUE oregexp_m_eqq(VALUE self, VALUE str) {
}
return Qtrue;
}
+/*
+* call-seq:
+* rxp =~ string => int or nil
+*
+* Matches <code>rxp</code> against <code>string</code>, returning the offset of the
+* start of the match or <code>nil</code> if the match failed. Sets $~ to the corresponding
+* <code>MatchData</code> or <code>nil</code>.
+*
+* ORegexp.new( 'SIT' ) =~ "insensitive" #=> nil
+* ORegexp.new( 'SIT', :options => OPTION_IGNORECASE ) =~ "insensitive" #=> 5
+**/
+static VALUE oregexp_match_op(VALUE self, VALUE str) {
+ VALUE ret = oregexp_match(self, str);
+ if(ret == Qnil)
+ return Qnil;
+ return INT2FIX(RMATCH(ret)->regs->beg[0]);
+}
+
void Init_oregexp() {
mOniguruma = rb_define_module("Oniguruma");
VALUE cORegexp = rb_define_class_under(mOniguruma, "ORegexp", rb_cObject);
rb_define_alloc_func(cORegexp, oregexp_allocate);
rb_define_method( cORegexp, "initialize", oregexp_initialize, 2 );
rb_define_method( cORegexp, "match", oregexp_match, 1 );
+ rb_define_method( cORegexp, "=~", oregexp_match_op, 1 );
rb_define_method( cORegexp, "gsub", oregexp_m_gsub, -1 );
rb_define_method( cORegexp, "sub", oregexp_m_sub, -1 );
rb_define_method( cORegexp, "gsub!", oregexp_m_gsub_bang, -1 );
View
@@ -276,23 +276,6 @@ def inspect
"/" + ORegexp.escape( @pattern ) + "/" + opt_str
end
- # call-seq:
- # rxp =~ string => int or nil
- #
- # Matches <code>rxp</code> against <code>string</code>, returning the offset of the
- # start of the match or <code>nil</code> if the match failed. Sets $~ to the corresponding
- # <code>MatchData</code> or <code>nil</code>.
- #
- # ORegexp.new( 'SIT' ) =~ "insensitive" #=> nil
- # ORegexp.new( 'SIT', :options => OPTION_IGNORECASE ) =~ "insensitive" #=> 5
-
- def =~ string
- return nil unless string
- m = match( string )
- return nil unless m
- m.begin(0)
- end
-
def source
@pattern.freeze
end
View
@@ -27,7 +27,7 @@ def test_last_match
end
def test_bad_initialization
- assert_raises(Exception) do
+ assert_raises(ArgumentError) do
reg = Oniguruma::ORegexp.new( "(3.)(.*)(3.))" )
end
end
@@ -127,6 +127,30 @@ def test_named_sub_backrefs
assert_equal('def123abc', re.sub('abc123def', '\<after>123\<pre>') )
end
+ def test_named_sub_backrefs_dupes
+ re = Oniguruma::ORegexp.new('(?<pre>\w+?)\d+(?<pre>\w+)')
+ assert_equal('123def', re.sub('abc123def', '123\<pre>') )
+ end
+
+ def test_backref_set_for_match
+ re = Oniguruma::ORegexp.new('Date:(\d{4})/(\d{2})/(\d{2})')
+ assert re.match( "Date:2007/03/25" )
+ assert_not_nil $~
+ assert_equal "2007", $1
+ assert_equal "03", $2
+ assert_equal "25", $3
+ end
+
+ def test_backref_set_for_match_op
+ re = Oniguruma::ORegexp.new('Date:(\d{4})/(\d{2})/(\d{2})')
+ assert re =~ "Date:2007/03/25"
+ assert_not_nil $~
+ assert_equal "2007", $1
+ assert_equal "03", $2
+ assert_equal "25", $3
+ end
+
+
end
class MatchDataTestCase < Test::Unit::TestCase

0 comments on commit bcf193b

Please sign in to comment.