[前][次][番号順一覧][スレッド一覧]

ruby-changes:4505

From: ko1@a...
Date: Mon, 14 Apr 2008 13:16:37 +0900 (JST)
Subject: [ruby-changes:4505] knu - Ruby:r15998 (ruby_1_8): * string.c (rb_str_partition, rb_str_rpartition,

knu	2008-04-14 13:16:23 +0900 (Mon, 14 Apr 2008)

  New Revision: 15998

  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/NEWS
    branches/ruby_1_8/string.c

  Log:
    * string.c (rb_str_partition, rb_str_rpartition,
      rb_str_start_with, rb_str_end_with): New methods:
      String#partition, #rpartition, #start_with? and #end_with?;
      backported from 1.9.  These methods are $KCODE aware unlike
      #index, #rindex and #include?.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/ChangeLog?r1=15998&r2=15997&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/NEWS?r1=15998&r2=15997&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/string.c?r1=15998&r2=15997&diff_format=u

Index: ruby_1_8/NEWS
===================================================================
--- ruby_1_8/NEWS	(revision 15997)
+++ ruby_1_8/NEWS	(revision 15998)
@@ -70,6 +70,14 @@
 
   * Regexp.union accepts an array of patterns.
 
+  * String#partition
+  * String#rpartition
+  * String#start_with?
+  * String#end_with?
+
+    New methods.  These are $KCODE aware unlike #index, #rindex and
+    #include?.
+
   * StopIteration
 
     New exception class that causes Kernel#loop to stop iteration when
Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 15997)
+++ ruby_1_8/ChangeLog	(revision 15998)
@@ -1,3 +1,16 @@
+Mon Apr 14 13:07:59 2008  Akinori MUSHA  <knu@i...>
+
+	* string.c (rb_str_partition, rb_str_rpartition,
+	  rb_str_start_with, rb_str_end_with): New methods:
+	  String#partition, #rpartition, #start_with? and #end_with?;
+	  backported from 1.9.  These methods are $KCODE aware unlike
+	  #index, #rindex and #include?.
+
+Mon Apr 14 00:11:22 2008  Akinori MUSHA  <knu@i...>
+
+	* struct.c (rb_struct_each, rb_struct_each_pair): Return
+	  an enumerator if no block is given.
+
 Sun Apr 13 15:55:52 2008  Kazuhiro NISHIYAMA  <zn@m...>
 
 	* object.c (sym_to_proc): new method Symbol#to_proc; backported
Index: ruby_1_8/string.c
===================================================================
--- ruby_1_8/string.c	(revision 15997)
+++ ruby_1_8/string.c	(revision 15998)
@@ -1941,7 +1941,31 @@
     return rb_reg_regcomp(pat);
 }
 
+static VALUE
+get_pat_quoted(pat)
+     VALUE pat;
+{
+    return get_pat(pat, 1);
+}
 
+static VALUE
+regcomp_failed(str)
+    VALUE str;
+{
+    rb_raise(rb_eArgError, "invalid byte sequence");
+    /*NOTREACHED*/
+    return Qundef;
+}
+
+static VALUE
+get_arg_pat(pat, quote)
+     VALUE pat;
+{
+    return rb_rescue2(get_pat_quoted, pat,
+                      regcomp_failed, pat,
+                      rb_eRegexpError, (VALUE)0);
+}
+
 /*
  *  call-seq:
  *     str.sub!(pattern, replacement)          => str or nil
@@ -4718,6 +4742,151 @@
     return rb_str_justify(argc, argv, str, 'c');
 }
 
+/*
+ *  call-seq:
+ *     str.partition(sep)              => [head, sep, tail]
+ *  
+ *  Searches the string for <i>sep</i> and returns the part before it,
+ *  the <i>sep</i>, and the part after it.  If <i>sep</i> is not
+ *  found, returns <i>str</i> and two empty strings.  If no argument
+ *  is given, Enumerable#partition is called.
+ *     
+ *     "hello".partition("l")         #=> ["he", "l", "lo"]
+ *     "hello".partition("x")         #=> ["hello", "", ""]
+ */
+
+static VALUE
+rb_str_partition(argc, argv, str)
+    int argc;
+    VALUE *argv;
+    VALUE str;
+{
+    VALUE sep;
+    long pos;
+
+    if (argc == 0) return rb_call_super(argc, argv);
+    rb_scan_args(argc, argv, "1", &sep);
+    if (TYPE(sep) != T_REGEXP) {
+	VALUE tmp;
+
+	tmp = rb_check_string_type(sep);
+	if (NIL_P(tmp)) {
+	    rb_raise(rb_eTypeError, "type mismatch: %s given",
+		     rb_obj_classname(sep));
+	}
+        sep = get_arg_pat(tmp);
+    }
+    pos = rb_reg_search(sep, str, 0, 0);
+    if (pos < 0) {
+      failed:
+	return rb_ary_new3(3, str, rb_str_new(0,0),rb_str_new(0,0));
+    }
+    sep = rb_str_subpat(str, sep, 0);
+    if (pos == 0 && RSTRING(sep)->len == 0) goto failed;
+    return rb_ary_new3(3, rb_str_substr(str, 0, pos),
+		          sep,
+		          rb_str_substr(str, pos+RSTRING(sep)->len,
+					     RSTRING(str)->len-pos-RSTRING(sep)->len));
+}
+
+/*
+ *  call-seq:
+ *     str.rpartition(sep)            => [head, sep, tail]
+ *  
+ *  Searches <i>sep</i> in the string from the end of the string, and
+ *  returns the part before it, the <i>sep</i>, and the part after it.
+ *  If <i>sep</i> is not found, returns two empty strings and
+ *  <i>str</i>.
+ *     
+ *     "hello".rpartition("l")         #=> ["hel", "l", "o"]
+ *     "hello".rpartition("x")         #=> ["", "", "hello"]
+ */
+
+static VALUE
+rb_str_rpartition(str, sep)
+    VALUE str;
+    VALUE sep;
+{
+    long pos = RSTRING(str)->len;
+
+    if (TYPE(sep) != T_REGEXP) {
+	VALUE tmp;
+
+	tmp = rb_check_string_type(sep);
+	if (NIL_P(tmp)) {
+	    rb_raise(rb_eTypeError, "type mismatch: %s given",
+		     rb_obj_classname(sep));
+	}
+        sep = get_arg_pat(tmp);
+    }
+    pos = rb_reg_search(sep, str, pos, 1);
+    if (pos < 0) {
+	return rb_ary_new3(3, rb_str_new(0,0),rb_str_new(0,0), str);
+    }
+    sep = rb_reg_nth_match(0, rb_backref_get());
+    return rb_ary_new3(3, rb_str_substr(str, 0, pos),
+		          sep,
+		          rb_str_substr(str, pos+RSTRING(sep)->len,
+					     RSTRING(str)->len-pos-RSTRING(sep)->len));
+}
+
+/*
+ *  call-seq:
+ *     str.start_with?([prefix]+)   => true or false
+ *  
+ *  Returns true if <i>str</i> starts with the prefix given.
+ */
+
+static VALUE
+rb_str_start_with(argc, argv, str)
+    int argc;
+    VALUE *argv;
+    VALUE str;
+{
+    int i;
+    long pos;
+    VALUE pat;
+
+    for (i=0; i<argc; i++) {
+	VALUE prefix = rb_check_string_type(argv[i]);
+	if (NIL_P(prefix)) continue;
+	if (RSTRING(str)->len < RSTRING(prefix)->len) continue;
+        pat = get_arg_pat(prefix);
+        if (rb_reg_search(pat, str, 0, 1) >= 0)
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+/*
+ *  call-seq:
+ *     str.end_with?([suffix]+)   => true or false
+ *  
+ *  Returns true if <i>str</i> ends with the suffix given.
+ */
+
+static VALUE
+rb_str_end_with(argc, argv, str)
+    int argc;
+    VALUE *argv;
+    VALUE str;
+{
+    int i;
+    long pos;
+    VALUE pat;
+
+    for (i=0; i<argc; i++) {
+	VALUE suffix = rb_check_string_type(argv[i]);
+	if (NIL_P(suffix)) continue;
+	if (RSTRING(str)->len < RSTRING(suffix)->len) continue;
+        pat = get_arg_pat(suffix);
+        pos = rb_reg_adjust_startpos(pat, str, RSTRING(str)->len - RSTRING(suffix)->len, 0);
+        if (rb_reg_search(pat, str, pos, 0) >= 0)
+            return Qtrue;
+    }
+    return Qfalse;
+}
+
 void
 rb_str_setter(val, id, var)
     VALUE val;
@@ -4807,6 +4976,8 @@
     rb_define_method(rb_cString, "to_sym", rb_str_intern, 0);
 
     rb_define_method(rb_cString, "include?", rb_str_include, 1);
+    rb_define_method(rb_cString, "start_with?", rb_str_start_with, -1);
+    rb_define_method(rb_cString, "end_with?", rb_str_end_with, -1);
 
     rb_define_method(rb_cString, "scan", rb_str_scan, 1);
 
@@ -4868,6 +5039,9 @@
     rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);
     rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);
 
+    rb_define_method(rb_cString, "partition", rb_str_partition, -1);
+    rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1);
+
     id_to_s = rb_intern("to_s");
 
     rb_fs = Qnil;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]