[macruby-changes] [3584] MacRuby/branches/icu

source_changes at macosforge.org source_changes at macosforge.org
Sat Feb 20 01:34:38 PST 2010


Revision: 3584
          http://trac.macosforge.org/projects/ruby/changeset/3584
Author:   lsansonetti at apple.com
Date:     2010-02-20 01:34:37 -0800 (Sat, 20 Feb 2010)
Log Message:
-----------
added String#match and String#=~

Modified Paths:
--------------
    MacRuby/branches/icu/re.cpp
    MacRuby/branches/icu/re.h
    MacRuby/branches/icu/string.c

Modified: MacRuby/branches/icu/re.cpp
===================================================================
--- MacRuby/branches/icu/re.cpp	2010-02-20 06:42:42 UTC (rev 3583)
+++ MacRuby/branches/icu/re.cpp	2010-02-20 09:34:37 UTC (rev 3584)
@@ -451,7 +451,7 @@
     return rb_reg_search(re, str, pos, 0);
 }
 
-static VALUE
+VALUE
 regexp_match(VALUE rcv, SEL sel, VALUE str)
 {
     const long pos = reg_match_pos(rcv, &str, 0);
@@ -489,7 +489,7 @@
  *  The return value is a value from block execution in this case.
  */
 
-static VALUE
+VALUE
 regexp_match2(VALUE rcv, SEL sel, int argc, VALUE *argv)
 {
     VALUE result, str, initpos;
@@ -1337,11 +1337,25 @@
 }
 
 VALUE
+rb_reg_regcomp(VALUE str)
+{
+    // XXX MRI caches the regexp here, maybe we should do the same...
+    return rb_reg_new_str(str, 0);
+}
+
+VALUE
 rb_reg_new(const char *cstr, long len, int options)
 {
     return rb_reg_new_str(rb_usascii_str_new(cstr, len), options);
 }
 
+VALUE
+rb_reg_quote(VALUE pat)
+{
+    // TODO
+    return pat;
+}
+
 void
 rb_match_busy(VALUE match)
 {

Modified: MacRuby/branches/icu/re.h
===================================================================
--- MacRuby/branches/icu/re.h	2010-02-20 06:42:42 UTC (rev 3583)
+++ MacRuby/branches/icu/re.h	2010-02-20 09:34:37 UTC (rev 3584)
@@ -14,7 +14,13 @@
 #endif
 
 bool rb_char_to_icu_option(int c, int *option);
+
 VALUE regexp_eqq(VALUE rcv, SEL sel, VALUE str);
+VALUE regexp_match(VALUE rcv, SEL sel, VALUE str);
+VALUE regexp_match2(VALUE rcv, SEL sel, int argc, VALUE *argv);
+
+VALUE rb_reg_quote(VALUE pat);
+VALUE rb_reg_regcomp(VALUE str);
 int rb_reg_search(VALUE re, VALUE str, int pos, bool reverse);
 
 static inline int

Modified: MacRuby/branches/icu/string.c
===================================================================
--- MacRuby/branches/icu/string.c	2010-02-20 06:42:42 UTC (rev 3583)
+++ MacRuby/branches/icu/string.c	2010-02-20 09:34:37 UTC (rev 3584)
@@ -1759,6 +1759,104 @@
     return str_inspect(self, true);
 }
 
+/*
+ *  call-seq:
+ *     str.match(pattern)   => matchdata or nil
+ *  
+ *  Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one),
+ *  then invokes its <code>match</code> method on <i>str</i>.  If the second
+ *  parameter is present, it specifies the position in the string to begin the
+ *  search.
+ *     
+ *     'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
+ *     'hello'.match('(.)\1')[0]   #=> "ll"
+ *     'hello'.match(/(.)\1/)[0]   #=> "ll"
+ *     'hello'.match('xx')         #=> nil
+ *     
+ *  If a block is given, invoke the block with MatchData if match succeed, so
+ *  that you can write
+ *     
+ *     str.match(pat) {|m| ...}
+ *     
+ *  instead of
+ *      
+ *     if m = str.match(pat)
+ *       ...
+ *     end
+ *      
+ *  The return value is a value from block execution in this case.
+ */
+
+static VALUE
+get_pat(VALUE pat, bool quote)
+{
+    switch (TYPE(pat)) {
+	case T_REGEXP:
+	    return pat;
+
+	case T_STRING:
+	    break;
+
+	default:
+	    {
+		VALUE val = rb_check_string_type(pat);
+		if (NIL_P(val)) {
+		    Check_Type(pat, T_REGEXP);
+		}
+		pat = val;
+	    }
+    }
+
+    if (quote) {
+	pat = rb_reg_quote(pat);
+    }
+    return rb_reg_regcomp(pat);
+}
+
+static VALUE
+rstr_match2(VALUE self, SEL sel, int argc, VALUE *argv)
+{
+    if (argc < 1) {
+	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
+    }
+    VALUE re = get_pat(argv[0], false);
+    argv[0] = self;
+    VALUE result = regexp_match2(re, 0, argc, argv);
+    if (!NIL_P(result) && rb_block_given_p()) {
+	return rb_yield(result);
+    }
+    return result;
+}
+
+/*
+ *  call-seq:
+ *     str =~ obj   => fixnum or nil
+ *  
+ *  Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match
+ *  against <i>str</i>,and returns the position the match starts, or 
+ *  <code>nil</code> if there is no match. Otherwise, invokes
+ *  <i>obj.=~</i>, passing <i>str</i> as an argument. The default
+ *  <code>=~</code> in <code>Object</code> returns <code>false</code>.
+ *     
+ *     "cat o' 9 tails" =~ /\d/   #=> 7
+ *     "cat o' 9 tails" =~ 9      #=> nil
+ */
+
+static VALUE
+rstr_match(VALUE self, SEL sel, VALUE other)
+{
+    switch (TYPE(other)) {
+	case T_STRING:
+	    rb_raise(rb_eTypeError, "type mismatch: String given");
+
+	case T_REGEXP:
+	    return regexp_match(other, 0, self);
+
+	default:
+	    return rb_funcall(other, rb_intern("=~"), 1, self);
+    }
+}
+
 // NSString primitives.
 
 static CFIndex
@@ -1825,6 +1923,8 @@
     rb_objc_define_method(rb_cRubyString, "intern", rstr_intern, 0);
     rb_objc_define_method(rb_cRubyString, "inspect", rstr_inspect, 0);
     rb_objc_define_method(rb_cRubyString, "dump", rstr_dump, 0);
+    rb_objc_define_method(rb_cRubyString, "match", rstr_match2, -1);
+    rb_objc_define_method(rb_cRubyString, "=~", rstr_match, 1);
 
     // Added for MacRuby (debugging).
     rb_objc_define_method(rb_cRubyString, "__chars_count__",
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100220/34a53ab7/attachment-0001.html>


More information about the macruby-changes mailing list