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

source_changes at macosforge.org source_changes at macosforge.org
Sat Feb 20 15:09:38 PST 2010


Revision: 3586
          http://trac.macosforge.org/projects/ruby/changeset/3586
Author:   lsansonetti at apple.com
Date:     2010-02-20 15:09:36 -0800 (Sat, 20 Feb 2010)
Log Message:
-----------
add String#scan

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 09:36:44 UTC (rev 3585)
+++ MacRuby/branches/icu/re.cpp	2010-02-20 23:09:36 UTC (rev 3586)
@@ -28,11 +28,6 @@
 
 #define RREGEXP(o) ((rb_regexp_t *)o)
 
-typedef struct rb_match_result {
-    unsigned int beg;
-    unsigned int end;
-} rb_match_result_t;
-
 typedef struct rb_match {
     struct RBasic basic;
     rb_regexp_t *regexp;
@@ -392,7 +387,7 @@
 		u_errorName(status));
     }
 
-    if (!matcher->find()) {
+    if (!matcher->find(pos, status)) {
 	delete unistr;
 	delete matcher;
 	rb_backref_set(Qnil);
@@ -1168,6 +1163,16 @@
  *
  */
 
+rb_match_result_t *
+rb_reg_match_results(VALUE match, int *count)
+{
+    assert(match != Qnil);
+    if (count != NULL) {
+	*count = RMATCH(match)->results_count;
+    }
+    return RMATCH(match)->results;
+}
+
 VALUE
 rb_reg_nth_match(int nth, VALUE match)
 {

Modified: MacRuby/branches/icu/re.h
===================================================================
--- MacRuby/branches/icu/re.h	2010-02-20 09:36:44 UTC (rev 3585)
+++ MacRuby/branches/icu/re.h	2010-02-20 23:09:36 UTC (rev 3586)
@@ -23,6 +23,13 @@
 VALUE rb_reg_regcomp(VALUE str);
 int rb_reg_search(VALUE re, VALUE str, int pos, bool reverse);
 
+typedef struct rb_match_result {
+    unsigned int beg;
+    unsigned int end;
+} rb_match_result_t;
+
+rb_match_result_t *rb_reg_match_results(VALUE match, int *count);
+
 static inline int
 rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, bool reverse)
 {

Modified: MacRuby/branches/icu/string.c
===================================================================
--- MacRuby/branches/icu/string.c	2010-02-20 09:36:44 UTC (rev 3585)
+++ MacRuby/branches/icu/string.c	2010-02-20 23:09:36 UTC (rev 3586)
@@ -19,6 +19,8 @@
 #include "re.h"
 #include "objc.h"
 #include "id.h"
+#include "ruby/node.h"
+#include "vm.h"
 
 VALUE rb_cSymbol; 	// XXX move me outside
 VALUE rb_cByteString; 	// XXX remove all references about me, i'm dead
@@ -1857,6 +1859,82 @@
     }
 }
 
+/*
+ *  call-seq:
+ *     str.scan(pattern)                         => array
+ *     str.scan(pattern) {|match, ...| block }   => str
+ *  
+ *  Both forms iterate through <i>str</i>, matching the pattern (which may be a
+ *  <code>Regexp</code> or a <code>String</code>). For each match, a result is
+ *  generated and either added to the result array or passed to the block. If
+ *  the pattern contains no groups, each individual result consists of the
+ *  matched string, <code>$&</code>.  If the pattern contains groups, each
+ *  individual result is itself an array containing one entry per group.
+ *     
+ *     a = "cruel world"
+ *     a.scan(/\w+/)        #=> ["cruel", "world"]
+ *     a.scan(/.../)        #=> ["cru", "el ", "wor"]
+ *     a.scan(/(...)/)      #=> [["cru"], ["el "], ["wor"]]
+ *     a.scan(/(..)(..)/)   #=> [["cr", "ue"], ["l ", "wo"]]
+ *     
+ *  And the block form:
+ *     
+ *     a.scan(/\w+/) {|w| print "<<#{w}>> " }
+ *     print "\n"
+ *     a.scan(/(.)(.)/) {|x,y| print y, x }
+ *     print "\n"
+ *     
+ *  <em>produces:</em>
+ *     
+ *     <<cruel>> <<world>>
+ *     rceu lowlr
+ */
+
+static VALUE
+rstr_scan(VALUE self, SEL sel, VALUE pat)
+{
+    const bool block_given = rb_block_given_p();
+
+    pat = get_pat(pat, true);
+    long start = 0;
+
+    VALUE ary = 0;
+    if (!block_given) {
+	ary = rb_ary_new();
+    }
+
+    while (rb_reg_search(pat, self, start, false) >= 0) {
+	VALUE match = rb_backref_get();
+
+	int count = 0;
+	rb_match_result_t *results = rb_reg_match_results(match, &count);
+	assert(count > 0);
+	start = results[0].end;
+
+	VALUE scan_result;
+	if (count == 1) {
+	    scan_result = rb_reg_nth_match(0, match);
+	}
+	else {
+	    scan_result = rb_ary_new2(count);
+	    for (int i = 1; i < count; i++) {
+		rb_ary_push(scan_result, rb_reg_nth_match(i, match));
+	    }
+	}
+
+	if (block_given) {
+	    rb_yield(scan_result);
+	    rb_backref_set(match);
+	    RETURN_IF_BROKEN();
+	}
+	else {
+	    rb_ary_push(ary, scan_result);
+	}
+    }
+
+    return block_given ? self : ary;
+}
+
 // NSString primitives.
 
 static CFIndex
@@ -1884,6 +1962,7 @@
     rb_cNSString = (VALUE)objc_getClass("NSString");
     assert(rb_cNSString != 0);
     rb_cString = rb_cNSString;
+    rb_include_module(rb_cString, rb_mComparable);
     rb_cNSMutableString = (VALUE)objc_getClass("NSMutableString");
     assert(rb_cNSMutableString != 0);
 
@@ -1925,6 +2004,7 @@
     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);
+    rb_objc_define_method(rb_cRubyString, "scan", rstr_scan, 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/79d51d02/attachment.html>


More information about the macruby-changes mailing list