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

ruby-changes:12833

From: matz <ko1@a...>
Date: Mon, 17 Aug 2009 07:45:11 +0900 (JST)
Subject: [ruby-changes:12833] Ruby:r24562 (trunk): * string.c (rb_str_upto): generate numerical sequence when

matz	2009-08-17 07:43:48 +0900 (Mon, 17 Aug 2009)

  New Revision: 24562

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24562

  Log:
    * string.c (rb_str_upto): generate numerical sequence when
      characters in both edges are all digits.  [ruby-talk:343186]

  Modified files:
    trunk/ChangeLog
    trunk/string.c
    trunk/test/ruby/test_range.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 24561)
+++ ChangeLog	(revision 24562)
@@ -395,6 +395,11 @@
 
 	* debug.c (ruby_dummy_gdb_enums): made public.  [ruby-dev:39001]
 
+Wed Aug  5 13:49:09 2009  Yukihiro Matsumoto  <matz@r...>
+
+	* string.c (rb_str_upto): generate numerical sequence when
+	  characters in both edges are all digits.  [ruby-talk:343186]
+
 Wed Aug  5 12:54:00 2009  Nobuyoshi Nakada  <nobu@r...>
 
 	* eval.c (rb_exc_raise, rb_exc_fatal): require exception object.
Index: string.c
===================================================================
--- string.c	(revision 24561)
+++ string.c	(revision 24562)
@@ -3070,7 +3070,7 @@
     VALUE end, exclusive;
     VALUE current, after_end;
     ID succ;
-    int n, excl;
+    int n, excl, ascii;
     rb_encoding *enc;
 
     rb_scan_args(argc, argv, "11", &end, &exclusive);
@@ -3079,8 +3079,9 @@
     CONST_ID(succ, "succ");
     StringValue(end);
     enc = rb_enc_check(beg, end);
-    if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 &&
-	is_ascii_string(beg) && is_ascii_string(end)) {
+    ascii = (is_ascii_string(beg) && is_ascii_string(end));
+    /* single character */
+    if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
 	char c = RSTRING_PTR(beg)[0];
 	char e = RSTRING_PTR(end)[0];
 
@@ -3093,6 +3094,47 @@
 	}
 	return beg;
     }
+    /* both edges are all digits */
+    if (ascii && ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0])) {
+	char *s, *send;
+	VALUE b, e;
+
+	s = RSTRING_PTR(beg); send = RSTRING_END(beg);
+	while (s < send) {
+	    if (!ISDIGIT(*s)) goto no_digits;
+	    s++;
+	}
+	s = RSTRING_PTR(end); send = RSTRING_END(end);
+	while (s < send) {
+	    if (!ISDIGIT(*s)) goto no_digits;
+	    s++;
+	}
+	b = rb_str_to_inum(beg, 10, Qfalse);
+	e = rb_str_to_inum(end, 10, Qfalse);
+	if (FIXNUM_P(b) && FIXNUM_P(e)) {
+	    long bi = FIX2LONG(b);
+	    long ei = FIX2LONG(e);
+	    char buf[sizeof(long)*3+1];
+
+	    while (bi <= ei) {
+		if (excl && bi == ei) break;
+		sprintf(buf, "%ld", bi);
+		rb_yield(rb_usascii_str_new_cstr(buf));
+		bi++;
+	    }
+	}
+	else {
+	    ID op = excl ? '<' : rb_intern("<=");
+
+	    while (rb_funcall(b, op, 1, e)) {
+		rb_yield(rb_obj_as_string(b));
+		b = rb_funcall(b, succ, 0, 0);
+	    }
+	}
+	return beg;
+    }
+    /* normal case */
+  no_digits:
     n = rb_str_cmp(beg, end);
     if (n > 0 || (excl && n == 0)) return beg;
 
Index: test/ruby/test_range.rb
===================================================================
--- test/ruby/test_range.rb	(revision 24561)
+++ test/ruby/test_range.rb	(revision 24562)
@@ -9,6 +9,12 @@
     assert_equal(["a", "b"], ("a" .. "b").to_a)
   end
 
+  def test_range_numeric_string
+    assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]")
+    assert_equal(["6", "7"], ("6"..."8").to_a)
+    assert_equal(["9", "10"], ("9".."10").to_a)
+  end
+
   def test_evaluation_order
     arr = [1,2]
     r = (arr.shift)..(arr.shift)

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

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