Skip to content
This repository
Browse code

added String#match and String#=~

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/branches/icu@3584 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
commit 80cdbfa1ade034bcae40dd280f43fb7f10a0818f 1 parent 1775a38
authored February 20, 2010
18  re.cpp
@@ -451,7 +451,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos)
451 451
     return rb_reg_search(re, str, pos, 0);
452 452
 }
453 453
 
454  
-static VALUE
  454
+VALUE
455 455
 regexp_match(VALUE rcv, SEL sel, VALUE str)
456 456
 {
457 457
     const long pos = reg_match_pos(rcv, &str, 0);
@@ -489,7 +489,7 @@ regexp_match(VALUE rcv, SEL sel, VALUE str)
489 489
  *  The return value is a value from block execution in this case.
490 490
  */
491 491
 
492  
-static VALUE
  492
+VALUE
493 493
 regexp_match2(VALUE rcv, SEL sel, int argc, VALUE *argv)
494 494
 {
495 495
     VALUE result, str, initpos;
@@ -1337,11 +1337,25 @@ rb_reg_new_str(VALUE str, int options)
1337 1337
 }
1338 1338
 
1339 1339
 VALUE
  1340
+rb_reg_regcomp(VALUE str)
  1341
+{
  1342
+    // XXX MRI caches the regexp here, maybe we should do the same...
  1343
+    return rb_reg_new_str(str, 0);
  1344
+}
  1345
+
  1346
+VALUE
1340 1347
 rb_reg_new(const char *cstr, long len, int options)
1341 1348
 {
1342 1349
     return rb_reg_new_str(rb_usascii_str_new(cstr, len), options);
1343 1350
 }
1344 1351
 
  1352
+VALUE
  1353
+rb_reg_quote(VALUE pat)
  1354
+{
  1355
+    // TODO
  1356
+    return pat;
  1357
+}
  1358
+
1345 1359
 void
1346 1360
 rb_match_busy(VALUE match)
1347 1361
 {
6  re.h
@@ -14,7 +14,13 @@ extern "C" {
14 14
 #endif
15 15
 
16 16
 bool rb_char_to_icu_option(int c, int *option);
  17
+
17 18
 VALUE regexp_eqq(VALUE rcv, SEL sel, VALUE str);
  19
+VALUE regexp_match(VALUE rcv, SEL sel, VALUE str);
  20
+VALUE regexp_match2(VALUE rcv, SEL sel, int argc, VALUE *argv);
  21
+
  22
+VALUE rb_reg_quote(VALUE pat);
  23
+VALUE rb_reg_regcomp(VALUE str);
18 24
 int rb_reg_search(VALUE re, VALUE str, int pos, bool reverse);
19 25
 
20 26
 static inline int
100  string.c
@@ -1759,6 +1759,104 @@ rstr_dump(VALUE self, SEL sel)
1759 1759
     return str_inspect(self, true);
1760 1760
 }
1761 1761
 
  1762
+/*
  1763
+ *  call-seq:
  1764
+ *     str.match(pattern)   => matchdata or nil
  1765
+ *  
  1766
+ *  Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one),
  1767
+ *  then invokes its <code>match</code> method on <i>str</i>.  If the second
  1768
+ *  parameter is present, it specifies the position in the string to begin the
  1769
+ *  search.
  1770
+ *     
  1771
+ *     'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
  1772
+ *     'hello'.match('(.)\1')[0]   #=> "ll"
  1773
+ *     'hello'.match(/(.)\1/)[0]   #=> "ll"
  1774
+ *     'hello'.match('xx')         #=> nil
  1775
+ *     
  1776
+ *  If a block is given, invoke the block with MatchData if match succeed, so
  1777
+ *  that you can write
  1778
+ *     
  1779
+ *     str.match(pat) {|m| ...}
  1780
+ *     
  1781
+ *  instead of
  1782
+ *      
  1783
+ *     if m = str.match(pat)
  1784
+ *       ...
  1785
+ *     end
  1786
+ *      
  1787
+ *  The return value is a value from block execution in this case.
  1788
+ */
  1789
+
  1790
+static VALUE
  1791
+get_pat(VALUE pat, bool quote)
  1792
+{
  1793
+    switch (TYPE(pat)) {
  1794
+	case T_REGEXP:
  1795
+	    return pat;
  1796
+
  1797
+	case T_STRING:
  1798
+	    break;
  1799
+
  1800
+	default:
  1801
+	    {
  1802
+		VALUE val = rb_check_string_type(pat);
  1803
+		if (NIL_P(val)) {
  1804
+		    Check_Type(pat, T_REGEXP);
  1805
+		}
  1806
+		pat = val;
  1807
+	    }
  1808
+    }
  1809
+
  1810
+    if (quote) {
  1811
+	pat = rb_reg_quote(pat);
  1812
+    }
  1813
+    return rb_reg_regcomp(pat);
  1814
+}
  1815
+
  1816
+static VALUE
  1817
+rstr_match2(VALUE self, SEL sel, int argc, VALUE *argv)
  1818
+{
  1819
+    if (argc < 1) {
  1820
+	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
  1821
+    }
  1822
+    VALUE re = get_pat(argv[0], false);
  1823
+    argv[0] = self;
  1824
+    VALUE result = regexp_match2(re, 0, argc, argv);
  1825
+    if (!NIL_P(result) && rb_block_given_p()) {
  1826
+	return rb_yield(result);
  1827
+    }
  1828
+    return result;
  1829
+}
  1830
+
  1831
+/*
  1832
+ *  call-seq:
  1833
+ *     str =~ obj   => fixnum or nil
  1834
+ *  
  1835
+ *  Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match
  1836
+ *  against <i>str</i>,and returns the position the match starts, or 
  1837
+ *  <code>nil</code> if there is no match. Otherwise, invokes
  1838
+ *  <i>obj.=~</i>, passing <i>str</i> as an argument. The default
  1839
+ *  <code>=~</code> in <code>Object</code> returns <code>false</code>.
  1840
+ *     
  1841
+ *     "cat o' 9 tails" =~ /\d/   #=> 7
  1842
+ *     "cat o' 9 tails" =~ 9      #=> nil
  1843
+ */
  1844
+
  1845
+static VALUE
  1846
+rstr_match(VALUE self, SEL sel, VALUE other)
  1847
+{
  1848
+    switch (TYPE(other)) {
  1849
+	case T_STRING:
  1850
+	    rb_raise(rb_eTypeError, "type mismatch: String given");
  1851
+
  1852
+	case T_REGEXP:
  1853
+	    return regexp_match(other, 0, self);
  1854
+
  1855
+	default:
  1856
+	    return rb_funcall(other, rb_intern("=~"), 1, self);
  1857
+    }
  1858
+}
  1859
+
1762 1860
 // NSString primitives.
1763 1861
 
1764 1862
 static CFIndex
@@ -1825,6 +1923,8 @@ Init_String(void)
1825 1923
     rb_objc_define_method(rb_cRubyString, "intern", rstr_intern, 0);
1826 1924
     rb_objc_define_method(rb_cRubyString, "inspect", rstr_inspect, 0);
1827 1925
     rb_objc_define_method(rb_cRubyString, "dump", rstr_dump, 0);
  1926
+    rb_objc_define_method(rb_cRubyString, "match", rstr_match2, -1);
  1927
+    rb_objc_define_method(rb_cRubyString, "=~", rstr_match, 1);
1828 1928
 
1829 1929
     // Added for MacRuby (debugging).
1830 1930
     rb_objc_define_method(rb_cRubyString, "__chars_count__",

0 notes on commit 80cdbfa

Please sign in to comment.
Something went wrong with that request. Please try again.